440 votes

Comment réimporter un paquet mis à jour dans l'interpréteur Python ?

Je teste souvent mon module dans l'interpréteur Python, et quand je vois une erreur, je mets rapidement à jour le fichier .py. Mais comment faire pour que cela se reflète dans l'interpréteur ? Jusqu'à présent, j'ai quitté et réintégré l'interpréteur parce que la réimportation du fichier ne fonctionne pas pour moi.

2 votes

Il semble que cette question ait été posée/répondue avant la sortie de reimport. Voir ma réponse ci-dessous pour de nouvelles informations.

3 votes

Les importations en Python sont mises en cache, donc normalement la deuxième importation et les suivantes obtiennent le même code même si le fichier a changé.

367voto

allyourcode Points 5670

Utilisez le reload fonction intégrée :

https://docs.python.org/2/library/functions.html#reload

Lorsque reload(module) est exécuté :

  • Le code des modules Python est recompilé et le code au niveau du module est réexécuté, définissant un nouvel ensemble d'objets qui sont liés à des noms dans le dictionnaire du module. La fonction init des modules d'extension n'est pas appelée une seconde fois.
  • Comme pour tous les autres objets de Python, les anciens objets ne sont récupérés que lorsque le nombre de leurs références tombe à zéro.
  • Les noms de l'espace de noms du module sont mis à jour pour pointer vers tout objet nouveau ou modifié.
  • Les autres références aux anciens objets (comme les noms externes au module) ne sont pas rebondis pour faire référence aux nouveaux objets et doivent être mis à jour dans chaque espace de nom où ils apparaissent si cela est souhaité.

Exemple :

# Make a simple function that prints "version 1"
shell1$ echo 'def x(): print "version 1"' > mymodule.py

# Run the module
shell2$ python
>>> import mymodule
>>> mymodule.x()
version 1

# Change mymodule to print "version 2" (without exiting the python REPL)
shell2$ echo 'def x(): print "version 2"' > mymodule.py

# Back in that same python session
>>> reload(mymodule)
<module 'mymodule' from 'mymodule.pyc'>
>>> mymodule.x()
version 2

16 votes

Notez que reload ne recharge que les modules spécifiés ; les importations de ce module doivent également être rechargées individuellement.

0 votes

J'ai essayé, mais ça n'a pas marché pour moi. Dans mon cas, c'est une classe Fichier MyClass.py classe MyClass : def __init__(self) : return 1 def do_some_work(self) : work = 2 + 3 print work

7 votes

Notez également que tous les objets qui font référence à un élément du module (comme une instance dont la classe est définie dans le module) continueront à utiliser l'ancien élément pré-rechargé. En général, le redémarrage de l'interpréteur est la façon la plus propre de procéder.

221voto

kawing-chiu Points 103

Toutes les réponses ci-dessus concernant reload() ou imp.reload() sont obsolètes.

reload() n'est plus une fonction intégrée dans python 3 et imp.reload() est marqué comme déprécié (voir help(imp)).

Il est préférable d'utiliser importlib.reload() à la place.

1 votes

Merci. Je ne vois pas pourquoi cette réponse n'a pas de votes positifs. Aucune des autres solutions ne fonctionne dans Python 3.4.

4 votes

Notez que cela prend un module comme argument, et non str .

0 votes

Ça ne marche pas pour moi. J'obtiens un message dans le repl, disant que le module n'a pas de méthode comme celle-là.

38voto

bobince Points 270740

Jusqu'à présent, j'ai quitté et réintroduit l'interpréteur parce que la réimportation du fichier ne fonctionne pas pour moi.

Oui, je dis ça comme ça. import vous donne à nouveau la copie existante du module de sys.modules .

Vous pouvez dire reload(module) de mettre à jour sys.modules et obtenir une nouvelle copie de ce module unique, mais si d'autres modules ont une référence au module original ou tout objet du module d'origine ils garderont leurs anciennes références et des choses très confuses se produiront.

Donc si vous avez un module a qui dépend du module b et b vous devez "recharger b" puis "recharger a". Si vous avez deux modules qui dépendent l'un de l'autre, ce qui est extrêmement fréquent lorsque ces modules font partie du même paquet, vous ne pouvez pas les recharger tous les deux : si vous rechargez p.a il obtiendra une référence à l'ancien p.b et vice versa. La seule façon de le faire est de les décharger tous les deux en une seule fois en supprimant leurs éléments de sys.modules avant de les importer à nouveau. C'est dégoûtant et il y a quelques pièges pratiques liés au fait que les entrées de modules ne sont pas considérées comme un marqueur d'échec d'importation relative.

Et si vous avez un module qui passe des références à ses objets aux modules système - par exemple, il enregistre un codec ou ajoute un gestionnaire d'avertissements - vous êtes coincé ; vous ne pouvez pas recharger le module système sans perturber le reste de l'environnement Python.

En résumé : pour tout sauf le cas le plus simple d'un module autonome chargé par un script autonome, reload() est très difficile à mettre en œuvre ; si, comme vous le laissez entendre, vous utilisez un "paquet", il est probablement préférable de continuer à faire tourner l'interpréteur.

0 votes

Cependant, si vous parlez d'un scénario de test et d'un test unitaire changeant script, exécuter reload sur le sut devrait fonctionner parfaitement. En fait, je me demande si l'ajout de "reload(sut module)" ne devrait pas être quelque chose que j'inclus en standard dans les tests unitaires.

27voto

Paul Barry Points 101

Dans Python 3, le comportement change.

>>> import my_stuff

... faire quelque chose avec mon_stuff, puis plus tard :

>>>> import imp
>>>> imp.reload(my_stuff)

et vous obtenez un tout nouveau my_stuff rechargé.

15 votes

Et dans Python 3.4, imp est déprécié au profit de importlib : importlib.reload(my_stuff) .

10voto

vartec Points 53382

En gros, recharger comme dans l'asnwer d'allyourcode. Mais cela ne changera pas le code sous-jacent de l'objet déjà instancié ou des fonctions référencées. En prolongement de sa réponse :

#Make a simple function that prints "version 1"
shell1$ echo 'def x(): print "version 1"' > mymodule.py

# Run the module
shell2$ python
>>> import mymodule
>>> mymodule.x()
version 1
>>> x = mymodule.x
>>> x()
version 1
>>> x is mymodule.x
True

# Change mymodule to print "version 2" (without exiting the python REPL)
shell2$ echo 'def x(): print "version 2"' > mymodule.py

# Back in that same python session
>>> reload(mymodule)
<module 'mymodule' from 'mymodule.pyc'>
>>> mymodule.x()
version 2
>>> x()
version 1
>>> x is mymodule.x
False

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X