Ich habe einen lang laufenden Python-Server und möchte einen Dienst aktualisieren können, ohne den Server neu zu starten. Was ist der beste Weg, dies zu tun?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
python
module
reload
python-import
Mark Harrison
quelle
quelle
Antworten:
Sie können ein Modul neu laden, wenn es bereits importiert wurde, indem Sie die
reload
integrierte Funktion verwenden (nur Python 3.4+) :In Python 3
reload
wurde in dasimp
Modul verschoben . In 3.4imp
wurde zugunsten von abgelehntimportlib
undreload
zu letzterem hinzugefügt. Wenn Sie auf 3 oder höher abzielen, verweisen Sie beim Aufrufen entweder auf das entsprechende Modulreload
oder importieren Sie es.Ich denke, das ist was du willst. Webserver wie der Entwicklungsserver von Django verwenden dies, damit Sie die Auswirkungen Ihrer Codeänderungen sehen können, ohne den Serverprozess selbst neu zu starten.
Um aus den Dokumenten zu zitieren:
Wie Sie in Ihrer Frage festgestellt haben, müssen Sie
Foo
Objekte rekonstruieren , wenn sich dieFoo
Klasse imfoo
Modul befindet.quelle
X
kein Modul ist, können Sieimport sys; reload(sys.modules[X.__module__])
is_changed
Funktion nur eine beliebige Funktion ist, die Sie schreiben müssten. Es ist kein eingebautes. Beispielsweise könnte es möglicherweise die Datei öffnen, die dem zu importierenden Modul entspricht, und sie mit einer zwischengespeicherten Version unterscheiden, um festzustellen, ob sie sich geändert hat.In Python 3.0–3.3 würden Sie Folgendes verwenden:
imp.reload(module)
Die BDFL hat geantwortet diese Frage .
Allerdings
imp
wurde in 3.4 zugunsten vonimportlib
(danke @Stefan! ) Veraltet .Ich denke , deshalb würden Sie jetzt verwenden
importlib.reload(module)
, obwohl ich nicht sicher bin.quelle
reload(__builtins__)
ist gültig in 2.xEs kann besonders schwierig sein, ein Modul zu löschen, wenn es nicht reines Python ist.
Hier einige Informationen von: Wie lösche ich ein importiertes Modul wirklich?
quelle
setattr(package, "empty", None)
reload()
Lädt nur das oberste Modul neu, und alles, was sich darin befindet, wird nicht neu geladen, es sei denn, Sie löschen es zuerst aus sys.modules.reload(module)
, aber nur, wenn es völlig eigenständig ist. Wenn irgendetwas anderes einen Verweis auf das Modul (oder ein zum Modul gehörendes Objekt) enthält, werden subtile und merkwürdige Fehler angezeigt, die dadurch verursacht werden, dass der alte Code länger als erwartet herumhängt und Dinge wie dasisinstance
Nicht-Arbeiten in verschiedenen Versionen des Moduls gleicher Code.Wenn Sie Einwegabhängigkeiten haben, müssen Sie auch alle Module neu laden, die vom neu geladenen Modul abhängen, um alle Verweise auf den alten Code zu entfernen. Laden Sie dann die Module, die von den neu geladenen Modulen abhängen, rekursiv neu.
Wenn Sie zirkuläre Abhängigkeiten haben, was beispielsweise beim erneuten Laden eines Pakets sehr häufig vorkommt, müssen Sie alle Module in der Gruppe auf einmal entladen. Das kann man nicht machen
reload()
da jedes Modul erneut importiert wird, bevor seine Abhängigkeiten aktualisiert wurden, sodass sich alte Referenzen in neue Module einschleichen können.Die einzige Möglichkeit, dies in diesem Fall zu tun, ist das Hacken
sys.modules
, was nicht unterstützt wird. Siesys.modules
müssten jeden Eintrag löschen, den Sie beim nächsten Import neu laden möchten, und auch Einträge löschen, deren Werte sindNone
ein Implementierungsproblem im Zusammenhang mit dem Zwischenspeichern fehlgeschlagener relativer Importe behandeln sollen. Es ist nicht besonders schön, aber solange Sie eine vollständig in sich geschlossene Reihe von Abhängigkeiten haben, die keine Referenzen außerhalb der Codebasis belassen, ist es funktionsfähig.Es ist wahrscheinlich am besten, den Server neu zu starten. :-)
quelle
None
Werten ausarbeiten , da ich genau auf dieses Problem stoße: Ich lösche Elemente aussys.modules
und nach dem erneuten Import sind einige importierte AbhängigkeitenNone
.None
Einträge den Importmechanismus durchlaufen haben, als die "echten" Einträge gelöscht wurden, und ich kann es anscheinend nicht in 2.7 schaffen. In Zukunft ist dies sicherlich kein Problem mehr, da implizite relative Importe weg sind. In der ZwischenzeitNone
scheint das Löschen aller Einträge mit Wert das Problem zu beheben.reload
Funktion? Es ist integriert, Sie müssen keine Bibliothek importieren.quelle
nose.run()
auch nachreload(my_module)
%run my_module
[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
.import sys; import json; del sys.modules['json']; print(json.dumps([1]))
und json funktioniert das Modul immer noch, obwohl es nicht mehr in den sys.modules enthalten ist.Verwenden Sie für Python 2 die integrierte Funktion reload () :
Verwenden Sie für Python 2 und 3.2–3.3 reload from module imp :
Aber
imp
ist veraltet , da Version 3.4 für importlib , so verwenden:oder
quelle
from six import reload_module
(musspip install six
natürlich zuerst)from six.moves import reload_module
( doc )Mit dem folgenden Code können Sie Python 2/3 kompatibel machen:
Sie können es wie
reload()
in beiden Versionen verwenden, was die Sache einfacher macht.quelle
Die akzeptierte Antwort behandelt den Fall von X-Import Y nicht. Dieser Code behandelt es und den Standardimportfall auch:
Im Fall des erneuten Ladens weisen wir die Namen der obersten Ebene den Werten zu, die im neu geladenen Modul gespeichert sind, wodurch sie aktualisiert werden.
quelle
>>> from X import Y
dem Nachladen tun>>> __import__('X', fromlist='Y')
fromlist='*'
?from
in Importanweisungen einzustellen . Nur krasseimport <package>
und explizite package.symbol im Code. Beachten Sie, dass dies möglicherweise nicht immer möglich oder wünschenswert ist. (Hier ist eine Ausnahme: von zukünftigen Import print_function.)foo = reload(foo); from foo import *
Dies ist die moderne Art, ein Modul neu zu laden:
Wenn Sie Versionen von Python unterstützen möchten, die älter als 3.5 sind, versuchen Sie Folgendes:
Um es zu verwenden, führen Sie es aus
reload(MODULE)
und ersetzen Sie esMODULE
durch das Modul, das Sie neu laden möchten.Zum Beispiel
reload(math)
wird dasmath
Modul neu geladen .quelle
from importlib import reload
. Dann können Sie tunreload(MODULE_NAME)
. Diese Funktion ist nicht erforderlich.modulereload(MODULE_NAME)
ist mehr selbsterklärend als nurreload(MODULE_NAME)
und hat eine geringere Wahrscheinlichkeit, mit anderen Funktionen in Konflikt zu geraten.Wenn Sie sich nicht auf einem Server befinden, aber ein Modul entwickeln und häufig neu laden müssen, finden Sie hier einen guten Tipp.
Stellen Sie zunächst sicher, dass Sie die hervorragende IPython-Shell aus dem Jupyter Notebook-Projekt verwenden. Nach der Installation von Jupyter können Sie mit
ipython
oderjupyter console
oder noch besser beginnen.jupyter qtconsole
, wodurch Sie eine schöne farbige Konsole mit Code-Vervollständigung in jedem Betriebssystem erhalten.Geben Sie nun in Ihrer Shell Folgendes ein:
Jetzt jedes Mal Sie Ihr Skript ausführen, werden Ihre Module neu geladen.
Darüber hinaus
2
gibt es andere Optionen der Autoreload-Magie :quelle
Für diejenigen wie mich, die alle Module entladen möchten (wenn sie im Python-Interpreter unter Emacs ausgeführt werden ):
Weitere Informationen finden Sie unter Reloading Python-Module .
quelle
sys.modules.values()
einem Modul ist. Zum Beispiel: >>> type (sys.modules.values () [1]) <class 'email.LazyImporter'> Wenn ich also versuche, diesen Code auszuführen, fällt er um (ich weiß, dass er nicht als praktische Lösung gedacht ist, nur darauf hinweisen).if mod and mod.__name__ != "__main__": imp.reload(mod)
Enthought Traits hat ein Modul, das dafür ziemlich gut funktioniert. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Es wird jedes Modul, das geändert wurde, neu laden und andere Module und instanziierte Objekte aktualisieren, die es verwenden. Es funktioniert die meiste Zeit nicht mit
__very_private__
Methoden und kann an der Klassenvererbung ersticken, aber es erspart mir verrückte Zeit, die Host-Anwendung beim Schreiben von PyQt-Guis neu starten zu müssen, oder Dinge, die in Programmen wie Maya oder Nuke ausgeführt werden. Es funktioniert vielleicht 20-30% der Zeit nicht, aber es ist immer noch unglaublich hilfreich.Das Paket von Enthought lädt Dateien nicht neu, sobald sie sich ändern - Sie müssen es explizit aufrufen -, aber das sollte nicht allzu schwer zu implementieren sein, wenn Sie es wirklich brauchen
quelle
Diejenigen, die Python 3 verwenden und von importlib neu laden.
Wenn Sie Probleme haben, wie es scheint, dass das Modul nicht neu geladen wird ... Das liegt daran, dass es einige Zeit braucht, um pyc neu zu kompilieren (bis zu 60 Sekunden). Ich schreibe diesen Hinweis nur, damit Sie wissen, ob Sie diese Art von Problem haben.
quelle
2018-02-01
foo
muss im Voraus erfolgreich importiert werden.from importlib import reload
,reload(foo)
31.5. importlib - Die Implementierung der Dokumentation zu import - Python 3.6.4
quelle
Andere Option. Beachten Sie, dass Python standardmäßig
importlib.reload
die als Argument übergebene Bibliothek nur erneut importiert. Die von Ihrer Bibliothek importierten Bibliotheken werden nicht neu geladen. Wenn Sie viele Dateien geändert haben und ein etwas komplexes Paket importieren müssen, müssen Sie ein tiefes Neuladen durchführen .Wenn Sie IPython oder Jupyter installiert haben, können Sie eine Funktion verwenden, um alle Bibliotheken tief zu laden:
Wenn Sie Jupyter nicht haben, installieren Sie es mit diesem Befehl in Ihrer Shell:
quelle
reload() argument must be module
. Ich verwende einen benutzerdefinierten Funktionsimport und scheint nicht zu funktionieren. Die Verwendung von integrierten Modulen funktioniert. :-( Es ist Zeitverschwendung, iPython für jede kleine Änderung, die ich an meinem Code vorgenommen habe, neu zuBearbeiten (Antwort V2)
Die vorherige Lösung eignet sich nur zum Abrufen der Rücksetzinformationen, ändert jedoch nicht alle Referenzen (mehr als,
reload
aber weniger als erforderlich). Um auch alle Referenzen zu setzen, musste ich in den Garbage Collector gehen und die Referenzen dort neu schreiben. Jetzt funktioniert es wie ein Zauber!Beachten Sie, dass dies nicht funktioniert, wenn der GC ausgeschaltet ist oder wenn Daten neu geladen werden, die nicht vom GC überwacht werden. Wenn Sie sich nicht mit dem GC anlegen möchten, reicht Ihnen möglicherweise die ursprüngliche Antwort.
Neuer Code:
Ursprüngliche Antwort
Wie in der Antwort von @ bobince geschrieben , wird diese Instanz nicht überschrieben , wenn in einem anderen Modul bereits ein Verweis auf dieses Modul vorhanden ist (insbesondere wenn es mit dem
as
Schlüsselwort like importiert wurdeimport numpy as np
).Dies erwies sich für mich als ziemlich problematisch, wenn ich Tests anwendete, die einen "Clean-Slate" -Status der Konfigurationsmodule erforderten. Daher habe ich eine Funktion mit dem Namen geschrieben
reset_module
, dieimportlib
diereload
Funktion verwendet und alle Attribute des deklarierten Moduls rekursiv überschreibt. Es wurde mit Python Version 3.6 getestet.Hinweis: Vorsichtig verwenden! Die Verwendung dieser Module für nicht periphere Module (Module, die beispielsweise extern verwendete Klassen definieren) kann zu internen Problemen in Python führen (z. B. Probleme beim Beizen / Entbeizen).
quelle
Für mich im Fall von Abaqus ist es die Art und Weise, wie es funktioniert. Stellen Sie sich vor, Ihre Datei ist Class_VerticesEdges.py
quelle
Ich hatte große Probleme beim Versuch, etwas in Sublime Text neu zu laden, aber schließlich konnte ich dieses Dienstprogramm schreiben, um Module in Sublime Text basierend auf dem Code neu zu laden
sublime_plugin.py
der zum Neuladen von Modulen verwendet wird.Im Folgenden können Sie Module aus Pfaden mit Leerzeichen auf ihren Namen neu laden. Später nach dem Neuladen können Sie sie einfach wie gewohnt importieren.
Wenn Sie zum ersten Mal ausführen, sollte das Modul geladen werden. Wenn Sie jedoch später die Methode / Funktion erneut verwenden
run_tests()
können, werden die Testdateien neu geladen . Bei Sublime Text (Python 3.3.6
) passiert dies häufig, da der Interpreter nie geschlossen wird (es sei denn, Sie starten Sublime Text, dh denPython3.3
Interpreter, neu).quelle
Eine andere Möglichkeit könnte darin bestehen, das Modul in eine Funktion zu importieren. Auf diese Weise wird nach Abschluss der Funktion des Moduls Müll gesammelt.
quelle
sys.modules
.