2010-01-23 16 views
23

Ho recentemente modificato il layout di directory del mio programma: prima, avevo tutti i miei moduli nella cartella "principale". Ora li ho spostati in una directory chiamata dopo il programma e ho inserito uno __init__.py per creare un pacchetto.Decapaggio di Python dopo aver cambiato la directory di un modulo

Ora ho un singolo file .py nella mia directory principale che viene utilizzato per avviare il mio programma, che è molto più ordinato.

In ogni caso, il tentativo di caricare file decapitati da versioni precedenti del mio programma non funziona. Ricevo "ImportError: No module named tools" - che presumo sia perché il mio modulo era precedentemente nella cartella principale, e ora è in whyteboard.tools, non semplicemente semplici strumenti. Tuttavia, il codice che si sta importando nel modulo strumenti risiede nella stessa directory, quindi dubito che sia necessario specificare un pacchetto.

Quindi, il mio programma di directory simile a questa:

whyteboard-0.39.4

-->whyteboard.py

-->README.txt

-->CHANGELOG.txt

---->whyteboard/

---->whyteboard/__init__.py

---->whyteboard/gui.py

---->whyteboard/tools.py

whyteboard.py lancia un blocco di codice da Whyteboard/gui.py, che spara la GUI. Questo problema di pickling non stava sicuramente accadendo prima che la directory si riorganizzasse.

+0

Forse si può aggiungere il modulo al PYTHONPATH ('sys.path.append (path_to_your_module) ') prima del carico di pickle? –

risposta

41

Come dicono pickle's docs, al fine di salvare e ripristinare un'istanza di classe (in realtà una funzione, anche), è necessario rispettare alcuni vincoli:

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 non è il "lo stesso modulo come" tools (anche se può essere importato da import tools da altri moduli nello stesso pacchetto, finisce in sys.modules come sys.modules['whyteboard.tools']: questo è assolutamente cruciale, altrimenti lo stesso modulo importato da uno nello stesso pacchetto e uno in un altro pacchetto finirebbe con voci multiple e possibilmente in conflitto!).

Se i file sottaceto sono in un buon formato/avanzato (in contrapposizione al vecchio formato ASCII che è il default solo per motivi di compatibilità), loro migrazione, una volta che si esegue tali cambiamenti possono infatti non essere abbastanza banale come "modifica del file" (che è binario & c ...!), nonostante quale altra risposta suggerisca. Ti suggerisco invece di creare un piccolo "script di migrazione pickle": lascia che patch sia impostato su sys.modules in questo modo ...:

import sys 
from whyteboard import tools 

sys.modules['tools'] = tools 

e poi cPickle.load ogni file, del sys.modules['tools'], e cPickle.dump ogni oggetto caricato di nuovo in un file: che temporanea di entrata in più in sys.modules dovrebbe lasciare il carico di sottaceti con successo, poi scaricarli di nuovo dovrebbe essere utilizzando il modulo-nome giusto per le classi delle istanze (rimuovendo quella voce extra dovrebbe esserne sicuro).

+0

L'ho provato ma [perché non funziona] (http://stackoverflow.com/questions/39944487/pickle-load-importerror-no-module-named-doc2vec-ext) per me? :/ – displayname

1

Questo è il normale comportamento di pickle, gli oggetti non raccolti devono avere il loro defining module importable.

Dovresti essere in grado di modificare il percorso dei moduli (ad esempio da tools a whyteboard.tools) modificando i file in salamoia, in quanto sono normalmente semplici file di testo.

3

pickle serializza le classi in base al riferimento, quindi se si cambia la classe, non si annullerà perché la classe non verrà trovata. Se si utilizza dill anziché pickle, è possibile serializzare le classi in base al riferimento o direttamente (serializzando direttamente la classe anziché il suo percorso di importazione). Si simula questo facilmente abbastanza semplicemente cambiando la definizione della classe dopo un dump e prima di un load.

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

successo a me, risolto con l'aggiunta della nuova posizione del modulo a sys.path prima del caricamento salamoia:

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

qual è il valore di 'f'? – vikkyhacks

Problemi correlati