web-dev-qa-db-de.com

wie lade ich eine Klasse in eine Python-Shell?

Wenn ich ein Modul importiere, das eine Klasse mit demselben Namen definiert, die zu einem Paket gehört, wird es wegen des __init__.py des übergeordneten Pakets als Klasse und nicht als Modul importiert. Siehe verschiedene Importergebnisse in verschiedenen Verzeichnissen für Details. In der Python-Shell oder der ipython-Shell, wenn ich dies tue

from MyPak import MyMod

MyModule wird immer als Klasse importiert, daher kann ich es nicht neu laden (reload () funktioniert nur für Module). Lauf 

from MyPak import MyMod

scheint die Klassendefinition erneut nicht zu aktualisieren. Könnte jemand eine Möglichkeit vorschlagen, die Klasse in der Python-Shell zu aktualisieren? 

ps. ohne den Python-Interpreter neu zu starten. 

pps. Nur für den Fall, dass Sie den Code in der Hand haben und ihn testen möchten: Ich spreche eigentlich von BioPython und arbeite an Bio.PDB.PDBParser. Ich habe eine ipython-Shell (v0.10) und bearbeite PDBParser.py. Ich habe gerade keine Möglichkeit, es in ipython neu zu laden.

also hier ist was ich getan habe:

# start ipython v0.10
import Bio
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure()
# then I make changes,e.g. simply print some text, in PDBParser.py
del Bio
del PDBParser
del s
import Bio  # or reload(Bio) without deleting all the objects
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure() # expected output after change not seen :(

Ich konnte den gedruckten Text nicht sehen. Die Änderungen wurden irgendwie nicht angewendet. 

50
HongboZhu

Endlich fand ich die Antwort:

import MyPak
from MyPak import MyMod

nach der Bearbeitung der MyPak/MyMod.py-Datei muss die Klasse MyMod in die Datei MyMod.py erneut geladen werden

import sys
del sys.modules['MyPak.MyMod'] 
reload(MyPak)
from MyPak import MyMod

Vorbehalte:

  1. Die Ausführung von del MyPak oder del MyMod oder del MyPak.MyMod löst das Problem nicht, da die Namensbindung einfach entfernt wird. Python durchsucht nur sys.modules, um festzustellen, ob die Module bereits importiert wurden. Schauen Sie sich die Diskussion unter post module in sys.modules und globals () an.

  2. Beim erneuten Laden von MyPak versucht Python, die Zeile from MyMod import MyMod in MyPak/__init__.py auszuführen. Es findet jedoch MyPak.MyMod in sys.modules, also NICHT Reload MyMod, obwohl MyPak/MyMod.py aktualisiert wurde. Und Sie werden feststellen, dass kein neuer MyPak/MyMod.pyc generiert wird.

33
HongboZhu

Importieren Sie nur in Python 3 die Funktion reload :

>>> from importlib import reload

Auf Python 2.x und 3.x können Sie dann einfach reload für das Modul aufrufen:

>>> import MyPak
>>> reload(MyPak)
>>> from MyPak import MyMod

Instanzen der alten Klasse werden jedoch nicht aktualisiert (es gibt einfach keinen Code, der den Aktualisierungsmechanismus beschreibt).

57
phihag

Es gibt verschiedene Möglichkeiten, dies zu lösen:

1. Verwenden Sie import MyPak.MyMod anstelle von from MyPak import MyMod

Dann kannst du schreiben:

from importlib import reload  # If on Python 3
import MyPak.MyMod
reload(MyPak.MyMod)

und es funktioniert.

2. Verwenden Sie IPython.lib.deepreload

from MyPak import MyMod
from IPython.lib.deepreload import reload
reload(MyPak)  # This should also reload all submodules

3. Verwenden Sie Autoreload Magic

%load_ext autoreload
%autoreload 2
import MyPak.MyMod  # All changes to MyPak.MyMod will be loaded automatically
8
ostrokach

Ich habe eine Datei myfile.py, die eine Klasse MyClass enthält

Um zu importieren, machen Sie einfach:

from myfile import MyClass
mc = MyClass()

Neu laden:

import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()

Dies ist sehr nützlich beim Erstellen von Modulen. Sie können diese in eine Funktion einfügen und einfach die Funktion aufrufen

def myreload():
   import sys
   del sys.modules['myfile']
   from myfile import MyClass
   modifiedmc = MyClass()
   global mc
   mc = modifiedmc
5
Sancho George

Sie können eine Zauberfunktion verwenden:

%load_ext autoreload
%autoreload 2
from MyPak import MyMod
3

Es funktioniert für mich mit Python 3.5.2:

import importlib
importlib.reload(class)
from class import module
0
David Chen