En Python, une fois que j'ai importé un module X dans une session d'interprétation en utilisant import X
et que le module a été modifié à l'extérieur, je peux recharger le module avec reload(X)
. Les modifications deviennent alors disponibles dans ma session d’interprète.
Je me demande si cela est également possible lorsque j'importe un composant Y du module X à l'aide de from X import Y
.
L'instruction reload Y
ne fonctionne pas, car Y n'est pas un module, mais seulement un composant (dans ce cas, une classe) à l'intérieur d'un module.
Est-il possible de recharger des composants individuels d'un module sans quitter la session d'interprétation (ou importer le module entier)?
MODIFIER:
Pour plus de clarté, la question concerne l'importation d'un classe ou fonction Y à partir d'un module X et le rechargement d'une modification, pas un module Y à partir d'un package X.
Si Y est un module (et X un paquet) reload(Y)
ira bien - sinon, vous verrez pourquoi les bons guides de style Python (tels que ceux de mon employeur) disent à jamais importer quoi que ce soit sauf un module (C’est l’une des nombreuses bonnes raisons - mais les gens continuent d’importer directement des fonctions et des classes, peu importe le nombre de fois où j’explique que c’est pas une bonne idée ;-).
De mes tests. La réponse marquée, qui suggère un simple reload(X)
, ne fonctionne pas.
D'après ce que je peux dire, la réponse correcte est:
import X
reload( X )
from X import Y
Mon test était le suivant (Python 2.6.5 + bpython 0.9.5.2)
X.py:
def Y():
print "Test 1"
bpython:
>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X ) # doesn't work because X not imported yet
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2
>>> # Finally get what we were after
Tout d’abord, vous ne devriez pas du tout utiliser reload si vous pouvez l’éviter. Mais supposons que vous ayez vos raisons (c'est-à-dire le débogage dans IDLE).
Le rechargement de la bibliothèque ne récupérera pas les noms dans l'espace de noms du module. Pour ce faire, il suffit de réaffecter les variables:
f = open('Zoo.py', 'w')
f.write("snakes = ['viper','anaconda']\n")
f.close()
from Zoo import snakes
print snakes
f = open('Zoo.py', 'w')
f.write("snakes = ['black-adder','boa constrictor']\n")
f.close()
import Zoo
reload(Zoo)
snakes = Zoo.snakes # the variable 'snakes' is now reloaded
print snakes
Vous pouvez le faire de quelques autres manières. Vous pouvez automatiser le processus en effectuant une recherche dans l'espace de noms local et en réaffectant tout ce qui provient du module en question, mais je pense que nous sommes assez pervers.
from modulename import func
import sys
reload(sys.modules['modulename'])
from modulename import func
Si vous voulez faire ceci:
from mymodule import myobject
Faites ceci à la place:
import mymodule
myobject=mymodule.myobject
Vous pouvez maintenant utiliser myobject de la même manière que vous l'aviez prévu (sans les références illisibles et illisibles de mymodule partout).
Si vous travaillez de manière interactive et souhaitez recharger myobject à partir de mymodule, vous pouvez maintenant utiliser:
reload(mymodule)
myobject=mymodule.myobject
en supposant que vous avez utilisé from X import Y
, vous avez deux options:
reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module
ou
Y=reload(sys.modules['X']).Y
quelques considérations:
A. si la portée de l'importation n'est pas au niveau du module (par exemple, importation dans une fonction), vous devez utiliser la deuxième version.
B. si Y est importé dans X depuis un autre module (Z) - vous devez recharger Z, recharger X et recharger votre module, même recharger tous vos modules (par exemple, en utilisant [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]
) pourrait recharger X avant de recharger Z - et que de ne pas actualiser la valeur de Y.
reload()
module X
,reload()
important Y
à partir de X
.Notez que le rechargement ne changera pas les objets déjà créés liés dans d'autres espaces de noms (même si vous suivez le guide de style d'Alex).
Si vous travaillez dans un environnement Jupyter et que vous possédez déjà from module import function
pouvez utiliser la fonction magique, autoreload
de
%load_ext autoreload
%autoreload
from module import function
L'introduction du autoreload
dans IPython est donnée ici .
Pour faire suite à AlexMartelli et Catskul à ses réponses, il existe des cas très simples mais méchants qui semblent confondre reload
, du moins dans Python 2.
Supposons que j'ai l'arbre source suivant:
- foo
- __init__.py
- bar.py
avec le contenu suivant:
init.py:
from bar import Bar, Quux
bar.py:
print "Loading bar"
class Bar(object):
@property
def x(self):
return 42
class Quux(Bar):
object_count = 0
def __init__(self):
self.count = self.object_count
self.__class__.object_count += 1
@property
def x(self):
return super(Quux,self).x + 1
def __repr__(self):
return 'Quux[%d, x=%d]' % (self.count, self.x)
Cela fonctionne très bien sans utiliser reload
:
>>> from foo import Quux
Loading bar
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> Quux()
Quux[2, x=43]
Mais essayez de recharger et cela n’a aucun effet ou corrompt les choses:
>>> import foo
Loading bar
>>> from foo import Quux
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> reload(foo)
<module 'foo' from 'foo\__init__.pyc'>
>>> Quux()
Quux[2, x=43]
>>> from foo import Quux
>>> Quux()
Quux[3, x=43]
>>> reload(foo.bar)
Loading bar
<module 'foo.bar' from 'foo\bar.pyc'>
>>> Quux()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo\bar.py", line 17, in __repr__
return 'Quux[%d, x=%d]' % (self.count, self.x)
File "foo\bar.py", line 15, in x
return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> Quux().count
5
>>> Quux().count
6
>>> Quux = foo.bar.Quux
>>> Quux()
Quux[0, x=43]
>>> foo.Quux()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo\bar.py", line 17, in __repr__
return 'Quux[%d, x=%d]' % (self.count, self.x)
File "foo\bar.py", line 15, in x
return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> foo.Quux().count
8
La seule manière de pouvoir recharger le sous-module bar
était de reload(foo.bar)
; le seul moyen d’accéder à la classe Quux
rechargée est d’atteindre et de le saisir à partir du sous-module rechargé; mais le module foo
a lui-même conservé l'objet Quux
d'origine, probablement parce qu'il utilise from bar import Bar, Quux
(plutôt que import bar
suivi de Quux = bar.Quux
); De plus, la classe Quux
est désynchronisée avec ce qui est bizarre.