web-dev-qa-db-de.com

Wie kann ich ein Python-Modul entladen (neu laden)?

Ich habe einen Python-Server mit langer Laufzeit und möchte einen Dienst ohne Neustart des Servers aktualisieren können. Was tun Sie am besten?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
679
Mark Harrison

Sie können ein Modul erneut laden, wenn es bereits importiert wurde, indem Sie die Funktion reload builtin verwenden:

from importlib import reload  # Python 3.4+ only.
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

In Python 3 wurde reload in das Modul imp verschoben. In 3.4 wurde imp zugunsten von importlib abgelehnt, und reload wurde zu Letzterem hinzugefügt. Beim Targeting 3 oder höher referenzieren Sie entweder das entsprechende Modul, wenn Sie reload aufrufen, oder importieren Sie es.

Ich denke, das ist es 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:

Der Code für die Python-Module wird neu kompiliert und der Code auf Modulebene erneut ausgeführt wird Definieren eines neuen Satzes von Objekten, die sind an Namen im Modul gebunden Wörterbuch. Die init-Funktion von Erweiterungsmodule werden nicht als .__ bezeichnet. zweites Mal. Wie bei allen anderen Objekten In Python sind die alten Objekte nur nach ihrer Referenznummer zurückgefordert auf null fallen. Die Namen im Modul Der Namespace wird so aktualisiert, dass er auf ein beliebiges .__ verweist. neue oder geänderte Objekte. Andere Verweise auf die alten Objekte (z. B. Namen außerhalb des Moduls) sind nicht rebound, um auf die neuen Objekte zu verweisen und muss in jedem Namespace aktualisiert werden wo sie auftreten, wenn dies gewünscht wird.

Wie Sie in Ihrer Frage festgestellt haben, müssen Sie Foo-Objekte rekonstruieren, wenn sich die Foo-Klasse im foo-Modul befindet.

634
cdleary

In Python 3.0–3.3 würden Sie Folgendes verwenden: imp.reload(module)

Der BDFL hat beantwortet diese Frage.

In 3.4 wurde imp ZUGUNSTEN VON importlib (danke @Stefan! ) veraltet.

Ich denke, deshalb verwenden Sie jetzt importlib.reload(module) , obwohl ich mir nicht sicher bin.

241
Paul D. Waite

Das Löschen eines Moduls kann besonders schwierig sein, wenn es sich nicht um reines Python handelt.

Hier einige Informationen von: Wie lösche ich ein importiertes Modul wirklich?

Sie können sys.getrefcount () verwenden, um die tatsächliche Anzahl von .__ herauszufinden. Verweise.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3

Zahlen größer als 3 zeigen an, dass es wird schwer sein, die Modul. Die heimische "leer" (enthält nichts) Modul sollte .__ sein. Müll gesammelt nach

>>> del sys.modules["empty"]
>>> del empty

als dritte Referenz ist ein Artefakt der getrefcount () - Funktion.

81
Gregg Lind

reload(module), aber nur wenn es völlig eigenständig ist. Wenn irgendetwas anderes einen Verweis auf das Modul (oder auf ein Objekt, das zum Modul gehört) hat, werden subtile und merkwürdige Fehler verursacht, die durch den alten Code verursacht werden, der länger als erwartet abhängt, und Dinge wie isinstance, die nicht in verschiedenen Versionen von funktionieren der gleiche Code.

Wenn Sie einseitige Abhängigkeiten haben, müssen Sie auch alle vom reloaded-Modul abhängigen Module neu laden, um alle Verweise auf den alten Code zu entfernen. Laden Sie anschließend Module, die von den nachgeladenen Modulen abhängig sind, rekursiv.

Wenn Sie zirkuläre Abhängigkeiten haben, was beispielsweise beim erneuten Laden eines Pakets häufig vorkommt, müssen Sie alle Module in der Gruppe auf einmal entladen. Mit reload() ist dies nicht möglich, da jedes Modul erneut importiert wird, bevor seine Abhängigkeiten aktualisiert wurden. Alte Verweise können sich also in neue Module einschleichen.

In diesem Fall können Sie dies nur tun, indem Sie sys.modules hacken, was irgendwie nicht unterstützt wird. Sie müssen jeden sys.modules-Eintrag, den Sie beim nächsten Import erneut laden möchten, durchgehen und löschen. Außerdem müssen Sie Einträge löschen, deren Werte None sind, um ein Implementierungsproblem zu behandeln, das das Zwischenspeichern fehlgeschlagener relativer Importe betrifft. Es ist nicht besonders schön, aber solange Sie eine vollständig in sich geschlossene Gruppe von Abhängigkeiten haben, die keine Referenzen außerhalb der Codebase hinterlassen, ist dies machbar.

Es ist wahrscheinlich am besten, den Server neu zu starten. :-)

62
bobince
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
57
Kumaresan

Verwenden Sie für Python 2 die integrierte Funktion reload () :

reload(module)

Für Python 2 und 3.2–3.3 benutze reload vom Modul imp :

import imp
imp.reload(module)

Aber impist veraltet seit Version 3.4 zugunsten von importlib , verwenden Sie also:

import importlib
importlib.reload(module)

oder

from importlib import reload
reload(module)
49
goetzc

Der folgende Code ermöglicht die Kompatibilität mit Python 2/3:

try:
    reload
except NameError:
    # Python 3
    from imp import reload

Sie können es in beiden Versionen als reload() verwenden, was die Sache einfacher macht.

20
Matt Clarkson

Die akzeptierte Antwort behandelt den aus X importierten Y-Fall nicht. Dieser Code behandelt es und auch den Standardimportfall:

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

Im Fall des Neuladens weisen wir die Namen der obersten Ebene den im neu geladenen Modul gespeicherten Werten zu, wodurch sie aktualisiert werden.

15
Joseph Garvin

Dies ist die moderne Art, ein Modul neu zu laden:

from importlib import reload

Geben Sie einfach reload(MODULE_NAME) ein und ersetzen Sie MODULE_NAME durch den Namen des Moduls, das Sie neu laden möchten.

Zum Beispiel wird reload(math) die mathematische Funktion neu laden.

12
Richie Bendall

Wenn Sie nicht in einem Server sind, sondern in Entwicklung sind und häufig ein Modul neu laden müssen, ist hier ein guter Tipp.

Stellen Sie zunächst sicher, dass Sie die ausgezeichnete IPython Shell aus dem Jupyter Notebook-Projekt verwenden. Nach der Installation von Jupyter können Sie es mit ipython oder jupyter console oder noch besser mit jupyter qtconsole starten, wodurch Sie in jedem Betriebssystem eine Nice-farbige Konsole mit Code-Vervollständigung erhalten.

Geben Sie nun in Ihrer Shell Folgendes ein:

%load_ext autoreload
%autoreload 2

Nun, jedes Mal, wenn Sie Ihr Skript ausführen, werden Ihre Module neu geladen. 

Neben dem 2 gibt es noch andere Optionen der Autoreload-Magie :

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.
10
neves

Für diejenigen wie mich, die alle Module entladen möchten (beim Ausführen im Python-Interpreter unter Emacs ):

   for mod in sys.modules.values():
      reload(mod)

Weitere Informationen finden Sie in Python-Module neu laden.

6
Arkadiy

Enthought Traits hat ein Modul, das dafür ziemlich gut funktioniert. https://traits.readthedocs.org/de/4.3.0/_modules/traits/util/refresh.html

Es wird jedes geänderte Modul erneut laden und andere Module und instanziierte Objekte, die es verwenden, aktualisieren. Es funktioniert meistens nicht mit __very_private__-Methoden und kann die Klassenvererbung verschlucken, aber es erspart mir viel Zeit, die Host-Anwendung neu zu starten, wenn Sie PyQt guis schreiben oder in Programmen wie Maya oder Nuke . Es funktioniert vielleicht nicht 20-30% der Zeit, aber es ist immer noch unglaublich hilfreich.

Enthought's Paket lädt Dateien nicht sofort, wenn sie sich ändern - Sie müssen es explizit nennen -, aber das sollte nicht so schwer zu implementieren sein, wenn Sie es wirklich brauchen

5
flipthefrog

Diejenigen, die Python 3 verwenden und von importlib nachladen.

Wenn Sie Probleme haben, scheint das Modul nicht neu zu laden ... Das liegt daran, dass es einige Zeit dauert, um pyc neu zu kompilieren (bis zu 60 Sekunden).

4
PythonMan

2018-02-01

  1. das Modul foo muss vorab erfolgreich importiert werden. 
  2. from importlib import reload, reload(foo) 

31,5. importlib - Die Implementierung von import - Python 3.6.4 Dokumentation

3
JawSaw

Andere Option. Der Python-Standardcode importlib.reload importiert die als Argument übergebene Bibliothek einfach erneut. Es wird nicht lädt die Bibliotheken neu, die Ihre Bibliothek importiert. Wenn Sie viele Dateien geändert haben und ein etwas komplexes Paket zum Importieren haben, müssen Sie ein tiefes Nachladen ausführen. 

Wenn Sie IPython oder Jupyter installiert haben, können Sie eine Funktion verwenden, um alle Bibliotheken tief zu laden:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

Wenn Sie nicht über Jupyter verfügen, installieren Sie es mit diesem Befehl in Ihrer Shell:

pip3 install jupyter
3
neves

für mich im Fall von Abaqus ist es die Art und Weise, wie es funktioniert

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])
1
Matt S

Ich hatte Probleme beim Versuch, etwas in Sublime Text neu zu laden, aber schließlich konnte ich dieses Dienstprogramm schreiben, um Module auf Sublime Text basierend auf dem Code zu laden, den sublime_plugin.py zum Nachladen von Modulen verwendet.

Im Folgenden können Sie Module aus Pfaden mit Leerzeichen in ihren Namen neu laden. Anschließend können Sie sie nach dem Neuladen wie gewohnt importieren.

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __== "__main__":
    run_tests()

Wenn Sie zum ersten Mal ausführen, sollte dies das Modul laden. Wenn Sie später erneut die Methode/Funktion run_tests() verwenden können, werden die Testdateien erneut geladen. Bei Sublime Text (Python 3.3.6) geschieht dies häufig, weil sein Interpreter niemals geschlossen wird (es sei denn, Sie starten Sublime Text neu, d. H. Den Python3.3-Interpreter).

0
user

Ein anderer Weg könnte darin bestehen, das Modul in einer Funktion zu importieren. Wenn die Funktion abgeschlossen ist, wird auf diese Weise der Müll gesammelt. 

0
hackbot89