2010-01-23 9 views
23

Ich habe kürzlich das Verzeichnis-Layout meines Programms geändert: Vorher hatte ich alle meine Module im Ordner "main". Jetzt habe ich sie in ein Verzeichnis nach dem Programm verschoben und dort ein __init__.py platziert, um ein Paket zu machen.Python-Beizen nach dem Ändern des Verzeichnisses eines Moduls

Jetzt habe ich eine einzelne .py-Datei in meinem Hauptverzeichnis, die verwendet wird, um mein Programm zu starten, das viel besser ist.

Wie auch immer, der Versuch, gebeizte Dateien aus früheren Versionen meines Programms zu laden, schlägt fehl. Ich bekomme, "ImportError: Kein Modul namens Werkzeuge" - was ich denke, ist, weil mein Modul zuvor im Hauptordner war, und jetzt ist es in whyteboard.tools, nicht einfach Werkzeuge. Der Code, der im Tools-Modul importiert wird, befindet sich jedoch im selben Verzeichnis wie dieser, daher bezweifle ich, dass ein Paket angegeben werden muss.

Also, mein Programmverzeichnis sieht wie folgt aus etwas:

whyteboard-0.39.4

-->whyteboard.py

-->README.txt

-->CHANGELOG.txt

---->whyteboard/

---->whyteboard/__init__.py

---->whyteboard/gui.py

---->whyteboard/tools.py

whyteboard.py einen Codeblock startet vom Whyteboard/gui.py feuert, dass die GUI auf. Dieses Beizproblem trat definitiv nicht auf, bevor das Verzeichnis neu organisiert wurde.

+0

vielleicht Sie Ihr Modul PYTHONPATH hinzufügen ('sys.path.append (path_to_your_module) ') vor dem Pickle-Laden? –

Antwort

41

Wie pickle's docs sagen, um eine Klasseninstanz (eigentlich eine Funktion, auch) zu speichern und wiederherzustellen, müssen Sie bestimmte Einschränkungen beachten:

pickle can save and restore class instances transparently, however the class definition must be importable and live in the same module as when the object was stored

whyteboard.tools ist nicht das „das gleiche Modul wie“ tools (obwohl es durch import tools von anderen Modulen in dem gleichen Paket importiert werden kann, landet es in sys.modules als sys.modules['whyteboard.tools']: Dies ist absolut entscheidend, sonst das gleiche Modul von einem im selben Paket im Vergleich zu einem in einem anderen Paket importiert würde am Ende mit mehreren und möglicherweise widersprüchlichen Einträgen!).

Wenn Ihre Beize-Dateien sind in einem guten/Advanced Format (im Gegensatz zu dem alten ASCII-Format gegenüber, dass der Standard aus Kompatibilitätsgründen nur ist), die Migration sie, sobald Sie diese Änderungen durchführen kann in der Tat nicht ganz so trivial wie "editing the file" (das ist binär & c ...!), trotz was eine andere Antwort vorschlägt. Ich schlage vor, dass Sie stattdessen ein kleines "pickle-migrating script" machen: lassen Sie es so patchen sys.modules ...:

import sys 
from whyteboard import tools 

sys.modules['tools'] = tools 

und dann cPickle.load jede Datei, del sys.modules['tools'] und cPickle.dump jedes geladenes Objekt zu Datei zurück: die temporäre zusätzlicher Eintrag in sys.modules erfolgreich die Gurken Last lassen soll, Dumping sie dann sollte wieder die richtigen Modul-Namen verwenden für die Klassen der Instanzen (das Entfernen dieses zusätzlichen Eintrags sollte das sicherstellen).

+0

Ich habe das versucht, aber [warum funktioniert es nicht] (http://stackoverflow.com/questions/39944487/pickle-load-importerror-no-module-named-doc2vec-ext) für mich? :/ – displayname

1

Dies ist das normale Verhalten von Pickle, ungebackene Objekte müssen ihre defining module importable haben.

Sie sollten in der Lage sein, den Modulpfad (d. H. Von tools zu whyteboard.tools) zu ändern, indem Sie die eingelegten Dateien bearbeiten, da es sich normalerweise um einfache Textdateien handelt.

3

pickle serialisiert Klassen als Referenz, wenn Sie also ändern, dass die Klasse lebt, wird sie nicht unpickle, weil die Klasse nicht gefunden wird. Wenn Sie dill anstelle von pickle verwenden, können Sie Klassen durch Verweis oder direkt serialisieren (indem Sie die Klasse direkt serialisieren, anstatt den Importpfad zu verwenden). Sie simulieren dies ziemlich einfach, indem Sie einfach die Klassendefinition nach einer dump und vor einer load ändern.

Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> 
>>> class Foo(object): 
... def bar(self): 
...  return 5 
... 
>>> f = Foo() 
>>> 
>>> _f = dill.dumps(f) 
>>> 
>>> class Foo(object): 
... def bar(self, x): 
...  return x 
... 
>>> g = Foo() 
>>> f_ = dill.loads(_f) 
>>> f_.bar() 
5 
>>> g.bar(4) 
4 
2

mir passiert ist, löste es durch den neuen Standort des Moduls Zugabe vor dem Laden Gurke sys.path:

import sys 
sys.path.append('path/to/whiteboard') 
f = open("pickled_file", "rb") 
pickle.load(f) 
+0

Was ist der Wert von 'f'? – vikkyhacks

Verwandte Themen