Python: как Pickle работает с defaultdict - PullRequest
0 голосов
/ 09 ноября 2018

Я новичок в Python и играю с Pickle и не понимаю, как это работает

Я определяю defaultdict, напиши его, чтобы засолить. Затем в другом сценарии я прочитал его, и он по-прежнему ведет себя как defaultdict, даже не импортируя коллекции

script1:

import pickle
from collections import defaultdict

x = defaultdict(list)

x['a'].append(1)
print(x)

with open('pick','wb') as f:
    pickle.dump( x, f )

Скрипт2:

import pickle

with open('pick','rb') as f:
    x = pickle.load( f )

x['b'].append(2)
print(x)

y = dict()

try:
    y['b'].append(2)
    print(y)
except KeyError:
    print("Can't append to y")

работает:

$ python3 pick2.py
defaultdict(<class 'list'>, {'a': [1], 'b': [2]}) 
Can't append to y

Итак, 2-й скрипт не импортирует defaultdict, но засеченный x по-прежнему действует как один. Я в замешательстве:)

Как это работает в Python? Спасибо за любую информацию:)

1 Ответ

0 голосов
/ 04 декабря 2018

Прежде всего, если вы посмотрите на рассол документов , в частности:

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

Итак, это говорит нам о том, что pickle импортирует модуль, который определяет объект, который вы очищаете.

Мы можем показать это на небольшом примере, рассмотрим следующую структуру папок:

parent/
|-- a.py
|-- sub/

sub - это пустая подпапка
a.py содержит пример класса

# a.py
class ExampleClass:
    def __init__(self):
        self.var = 'This is a string'

Теперь запускаем консоль python в каталоге parent:

alex@toaster:parent$ python3
>>> import pickle
>>> from a import ExampleClass
>>> x = ExampleClass()
>>> x.var
'This is a string'
>>> with open('eg.p', 'wb') as f:
...     pickle.dump(x, f)

Выход из оболочки. Перейдите в каталог sub и попробуйте загрузить маринованный объект ExampleClass.

alex@toaster:sub$ python3
>>> import pickle
>>> with open('../eg.p', 'rb') as f:
...     x = pickle.load(f)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ModuleNotFoundError: No module named 'a'

Мы получаем ModuleNotFoundError, так как pickle не может загрузить определение класса из модуля a (он находится в другом каталоге). В вашем случае python может загрузить класс collections.defaultdict, так как этот модуль находится на PYTHONPATH. Однако, чтобы продолжить использовать модули, импортированные с помощью pickle, вам все равно придется импортировать их самостоятельно; например, вы хотите создать еще один defaultdict в script2.py.

Чтобы узнать больше о модулях, посмотрите здесь , в частности 6.1.2 Путь поиска модуля .

...