Подтвердить что ты не робот

Травление питона после изменения каталога модуля

Недавно я изменил свой макет каталога программ: раньше у меня были все мои модули внутри основной папки. Теперь я переместил их в каталог, названный в честь программы, и разместил там __init__.py, чтобы сделать пакет.

Теперь у меня есть один .py файл в моем основном каталоге, который используется для запуска моей программы, которая намного опрятна.

В любом случае попытка загрузки в маринованных файлах из предыдущих версий моей программы не выполняется. Я получаю: "ImportError: No module named tools" - я думаю, это потому, что мой модуль был ранее в основной папке, а теперь он в whyteboard.tools, а не просто в простых инструментах. Однако код, который импортируется в модуле tools, живет в том же каталоге, что и я, поэтому я сомневаюсь, что вам нужно указать пакет.

Итак, мой каталог программ выглядит примерно так:

whyteboard-0.39.4

-->whyteboard.py

-->README.txt

-->CHANGELOG.txt

---->whyteboard/

---->whyteboard/__init__.py

---->whyteboard/gui.py

---->whyteboard/tools.py

whyteboard.py запускает блок кода из whyboard/gui.py, который запускает GUI. Эта проблема травления определенно не происходила, прежде чем реорганизация каталога.

4b9b3361

Ответ 1

Как pickle docs говорят, что для сохранения и восстановления экземпляра класса (на самом деле это тоже функция) вы должны соблюдать определенные ограничения:

pickle может сохранять и восстанавливать класс случаев прозрачно, однако определение класса должно быть импортируемым и жить в том же модуле, что и при объект был сохранен

whyteboard.tools не "тот же модуль, что и" tools (хотя он может быть импортирован с помощью import tools другими модулями в одном пакете, он заканчивается на sys.modules как sys.modules['whyteboard.tools']: это абсолютно важно, иначе один и тот же модуль, импортированный одним из одного пакета в один и тот же пакет, будет иметь несколько и, возможно, конфликтующих записей!).

Если ваши файлы рассола находятся в хорошем/расширенном формате (в отличие от старого формата ascii, который по умолчанию используется только по соображениям совместимости), перенос их после выполнения таких изменений может фактически не столь же тривиальным, как "редактирование файла" (который является двоичным и c...!), несмотря на то, что предлагает другой ответ. Я предполагаю, что вместо этого вы делаете небольшой "pickle-migrating script": пусть это патч sys.modules вот так...:

import sys
from whyteboard import tools

sys.modules['tools'] = tools

а затем cPickle.load каждый файл, del sys.modules['tools'] и cPickle.dump каждый загруженный объект возвращается к файлу: эта временная дополнительная запись в sys.modules должна позволять соленьям загружаться успешно, а затем сбросить их снова следует использовать право module-name для классов экземпляров (удаление этой дополнительной записи должно быть уверенным в этом).

Ответ 2

pickle сериализует классы по ссылке, поэтому, если вы изменили жизнь класса, он не будет распаковываться, потому что класс не будет найден. Если вы используете dill вместо pickle, вы можете сериализовать классы по ссылке или напрямую (путем сериализации класса вместо пути импорта). Вы легко имитируете это, просто изменив определение класса после dump и до 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

Ответ 3

Случилось со мной, решив это, добавив новое местоположение модуля в sys.path перед загрузкой рассола:

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

Ответ 4

Это нормальное поведение рассола, незакрашенные объекты должны иметь определяющий модуль, импортируемый.

Вы должны иметь возможность изменить путь к модулю (т.е. от tools до whyteboard.tools), отредактировав маринованные файлы, поскольку они обычно являются простыми текстовыми файлами.