Unpickling python-Objekte mit einem geänderten Modul-Pfad
Ich versuche zu integrieren, ein Projekt Project A
gebaut, von einem Kollegen in ein anderes python-Projekt. Nun ist diese Kollegin nicht verwendet relative Importe in seinem code, sondern stattdessen getan
from packageA.moduleA import ClassA
from packageA.moduleA import ClassB
und folglich gebeizt die Klassen mit cPickle
. Für die Sauberkeit möchte ich ausblenden, das Paket, dass seine (Project A
) gebaut in meinem Projekt. Dies allerdings ändert sich der Pfad des definierten Klassen in packageA
. Kein problem, ich werde einfach neu definieren Sie den import mit
from ..packageA.moduleA import ClassA
from ..packageA.moduleA import ClassB
aber jetzt die un einlegen der Klassen schlägt mit der folgenden Meldung
with open(fname) as infile: self.clzA = cPickle.load(infile)
ImportError: No module named packageA.moduleA
Warum also nicht cPickle
anscheinend sehen das Modul defs. Muss ich hinzufügen, um die Wurzel des packageA
system Weg? Ist dies der korrekte Weg das problem zu lösen?
Den cPickled
Datei sieht so etwas wie
ccopy_reg
_reconstructor
p1
(cpackageA.moduleA
ClassA
p2
c__builtin__
object
p3
NtRp4
Dem alten Projekt-Hierarchie ist von der Art,
packageA/
__init__.py
moduleA.py
moduleB.py
packageB/
__init__.py
moduleC.py
moduleD.py
Möchte ich alle, die in einem WrapperPackage
MyPackage/
.. __init__.py
.. myModuleX.py
.. myModuleY.py
WrapperPackage/
.. __init__.py
.. packageA/
.. __init__.py
.. moduleA.py
.. moduleB.py
.. packageB/
.. __init__.py
.. moduleC.py
.. moduleD.py
- Ich stieß auf dieses problem schriftlich ein Plugin für KRunner. Der script-engine verwendet, die durch Plasma verwendet einen Pfad Haken zum erstellen einer fake-Paket, wo mein code war. Leider konnte ich keinen Weg, dies zu lösen. Das einzige, was ich tun konnte, war, manuell zu entfernen, Ihren Weg zu Haken, deaktivieren Sie das
sys
caches und importieren alles. Aber wenn Sie einige eingelegte Daten, dann müssen Sie unpickle es mit dem gleichen class Namen(das heißt, Sie müssen halten diefrom packageA.moduleA import ClassA
). Beachten Sie, dass einmal unpickled Sie können re-Gurke Sie mit dem richtigen Namen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie erstellen Sie einen alias für die pickle import arbeiten; die folgenden
__init__.py
- Datei desWrapperPackage
Paket:Kann es sein, dass Sie brauchen, um zusätzliche Einträge wenn:
Nun cPickle finden
packageA.moduleA
undpackageA.moduleB
wieder an Ihre alten Standorte.Möchten Sie vielleicht, um wieder schreiben die pickle-Datei danach das neue Modul-Position wird verwendet, damals. Die zusätzliche Aliase oben erstellt, sollte sicherstellen, dass die in Frage kommenden Modulen haben den neuen Standort name für
cPickle
zu Holen, wenn das schreiben der Klassen wieder.WrapperPackege.__init__.py
?WrapperPackage/__init__.py
Datei ist wahrscheinlich der beste Ort.import .something
ist ungültig, es mussfrom .something import module
?import .something
wirft einenSyntaxError
? python.org/dev/peps/pep-0328/#guido-s-decisionpackageA.moduleA
aber ich kann es laden ohne Probleme.obj = pickle.load(fh)
->pickle.dump(obj,fh2)
Zusätzlich zu @MartinPieters Antwort der andere Weg dies zu tun ist, um zu definieren, die
find_global
Methode dercPickle.Unpickler
Klasse, oder erweitern Sie diepickle.Unpickler
Klasse.Eine detailliertere Erläuterung des Prozesses für beide
pickle
undcPickle
finden hier.Eine mögliche Lösung ist, direkt Bearbeiten Sie die pickle-Datei (wenn Sie Zugriff haben). Ich lief in das gleiche problem von einem geänderten Modul Weg, und ich hatte die Dateien gespeichert haben, wie Gurke.HIGHEST_PROTOCOL so sollte es sein binary in der Theorie, aber das Modul Weg war, sitzen an der Spitze der pickle-Datei im Klartext. So habe ich nur ein suchen und ersetzen auf alle Instanzen des alten Modul-Pfad, mit dem neuen und voila, Sie korrekt geladen.
Ich bin sicher, diese Lösung ist nicht für jedermann, vor allem, wenn Sie haben eine sehr komplexe eingelegte Objekt, aber es ist eine quick-and-dirty-Daten fix, arbeitete für mich!
Dies ist meine grundlegende Muster für flexible unpickling - über eine eindeutige und schnelle transition-Karte - wie es in der Regel nur ein paar der bekannten Klassen neben den primitiven Daten-Typen, die relevant sind für das marinieren. Dies schützt auch unpickling gegen fehlerhafte oder bösartig konstruierte Daten, die nach allem kann die Ausführung von beliebigem python-code (!) auf einen einfachen
pickle.load()
(mit oder ohne Fehler-anfällig sys.Module hantieren).Python 2 & 3: