W Pythonie, po zaimportowaniu modułu X w sesji interpretera za pomocą import X
, a moduł zmienia się na zewnątrz, mogę ponownie załadować moduł za pomocą reload(X)
. Zmiany będą następnie dostępne w mojej sesji tłumacza.
Zastanawiam się, czy jest to również możliwe, gdy importuję komponent Y z modułu X za pomocą from X import Y
.
Instrukcja reload Y
nie działa, ponieważ Y nie jest samym modułem, a jedynie składnikiem (w tym przypadku klasą) wewnątrz modułu.
Czy w ogóle możliwe jest przeładowanie poszczególnych elementów modułu bez wychodzenia z sesji tłumacza (lub importowania całego modułu)?
EDYTOWAĆ:
Dla wyjaśnienia, pytanie dotyczy importowania klasy lub funkcji Y z modułu X i ponownego wczytywania zmiany, a nie modułu Y z pakietu X.
python
python-import
cschol
źródło
źródło
... possible ... import a component Y from module X
„kontraquestion is ... importing a class or function X from a module Y
”. Dodaję zmianę w tym celu.Odpowiedzi:
Jeśli Y jest modułem (a X pakietem)
reload(Y)
będzie dobrze - w przeciwnym razie zobaczysz, dlaczego dobre przewodniki w stylu Pythona (takie jak mój pracodawca) mówią, aby nigdy nie importować niczego poza modułem (jest to jeden z wielu ważnych powodów - mimo to ludzie nadal bezpośrednio importują funkcje i klasy, nieważne jak bardzo wyjaśniam, że to nie jest dobry pomysł ;-).źródło
import this
od interaktywnej zachęty, aby zobaczyć Zen of Python); i wszystkie powody, dla których przestrzenie nazw są świetnym pomysłem (natychmiastowe lokalne wizualne wskazówki, że nazwa jest wyszukiwana, łatwość mockowania / wstrzykiwania w testach, możliwość ponownego ładowania, możliwość elastycznej zmiany modułu poprzez przedefiniowanie niektórych wpisów, przewidywalna i kontrolowana zachowanie przy serializacji i odzyskiwaniu danych [[np. przez wytrawianie i wytrawianie]] i tak dalej, i tak dalej - komentarz SO nie jest wystarczająco długi, aby oddać sprawiedliwość temu bogatemu, długiemu argumentowi !!! -)importlib
pakietu.importlib.reload(Y)
docs.python.org/3.4/library/ ... zobacz także stackoverflow.com/questions/961162/ ...Odpowiedź
Z moich testów zaznaczona odpowiedź, która sugeruje prostą
reload(X)
, nie działa.Z tego, co mogę powiedzieć, poprawną odpowiedzią jest:
from importlib import reload # python 2.7 does not require this import X reload( X ) from X import Y
Test
Mój test był następujący (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
źródło
Foo
który ma moduł__init__.py
pobierający podmoduł ... Napiszę odpowiedź jako kontrprzykład.from modulename import func import importlib, sys importlib.reload(sys.modules['modulename']) from modulename import func
źródło
Po pierwsze, nie powinieneś w ogóle używać przeładowania, jeśli możesz tego uniknąć. Ale załóżmy, że masz swoje powody (np. Debugowanie wewnątrz IDLE).
Ponowne załadowanie biblioteki nie spowoduje przywrócenia nazw z powrotem do przestrzeni nazw modułu. Aby to zrobić, po prostu ponownie przypisz zmienne:
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
Możesz to zrobić na kilka innych sposobów. Możesz zautomatyzować ten proces, przeszukując lokalną przestrzeń nazw i ponownie przypisując wszystko, co pochodziło z danego modułu, ale myślę, że jesteśmy wystarczająco źli.
źródło
Jeśli chcesz to zrobić:
from mymodule import myobject
Zamiast tego zrób to:
import mymodule myobject=mymodule.myobject
Możesz teraz używać myobject w taki sam sposób, w jaki planowałeś (bez męczących, nieczytelnych odniesień do mymodułu wszędzie).
Jeśli pracujesz interaktywnie i chcesz ponownie załadować myobject z mymodule, możesz teraz użyć:
źródło
zakładając, że korzystałeś
from X import Y
, masz dwie możliwości:reload(sys.modules['X']) reload(sys.modules[__name__]) # or explicitly name your module
lub
Y=reload(sys.modules['X']).Y
kilka uwag:
A. jeśli zakres importu nie obejmuje całego modułu (np. Import w funkcji) - musisz użyć drugiej wersji.
B. jeśli Y jest importowany do X z innego modułu (Z) - musisz przeładować Z, a następnie przeładować X i przeładować moduł, nawet przeładowanie wszystkich modułów (np. Użycie
[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]
) może przeładować X przed ponownym załadowaniem Z - a następnie nie odświeżać wartości Y.źródło
reload()
modułX
,reload()
importowanie modułuY
zX
.Zauważ, że ponowne wczytanie nie zmieni już utworzonych obiektów powiązanych w innych przestrzeniach nazw (nawet jeśli zastosujesz się do przewodnika stylistycznego Alexa).
źródło
Jeśli pracujesz w środowisku jupyter i już masz,
from module import function
możesz użyć magicznej funkcji,autoreload
wg%load_ext autoreload %autoreload from module import function
Wprowadzenie do
autoreload
IPythona jest podane tutaj .źródło
Aby podążać za odpowiedziami Alexa Martellego i Catskula , istnieje kilka naprawdę prostych, ale paskudnych przypadków, które wydają się być zagmatwane
reload
, przynajmniej w Pythonie 2.Załóżmy, że mam następujące drzewo źródłowe:
o następującej treści:
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)
Działa to dobrze bez użycia
reload
:>>> from foo import Quux Loading bar >>> Quux() Quux[0, x=43] >>> Quux() Quux[1, x=43] >>> Quux() Quux[2, x=43]
Ale spróbuj ponownie załadować, a to albo nie ma wpływu, albo psuje rzeczy:
>>> 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
Jedynym sposobem mogę zapewnić
bar
submodule został załadowany byłoreload(foo.bar)
; jedynym sposobem, w jaki mogę uzyskać dostęp do przeładowanejQuux
klasy, jest sięgnięcie do niej i pobranie jej z ponownie załadowanego modułu podrzędnego; alefoo
sam moduł trzymał się oryginalnegoQuux
obiektu klasy, prawdopodobnie dlatego, że używafrom bar import Bar, Quux
(a nieimport bar
następuje po nimQuux = bar.Quux
); ponadtoQuux
klasa straciła synchronizację ze sobą, co jest po prostu dziwne.źródło