Как Pickle находит модули при загрузке из файла?Python

Программы на Python
Anonymous
Как Pickle находит модули при загрузке из файла?

Сообщение Anonymous »

Я пытаюсь понять, как работает травление, чтобы правильно спроектировать организацию своего репозитория. По сути, я выбираю объекты типа A, экземпляры которых содержат объекты типа B. A и B определены в модулях в отдельных пакетах:

Код: Выделить всё

project_dir
|
|-- package_a
|
|-- module_a  # class A is defined here
|
|-- package_b
|
|-- module_b # class B is defined here
Я провел эксперимент, который ожидал провала, учитывая мои знания о том, как работает травление, но он не вызвал исключения:

Код: Выделить всё

module_a.py:
class A:
name = "A"

Код: Выделить всё

module_b.py:
class B:
def __init__(self) -> None:
self.a = None
В одном окне терминала:

Код: Выделить всё

project_dir> python
>>> import pickle
>>> from package_a.module_a import A
>>> from package_b.module_b import B
>>> b_obj = B()
>>> b_obj.a = A()
>>> b_obj.a.name
'A'
>>> with open("b.pickle", "wb") as f:
...     pickle.dump(b_obj, f)
...
>>> exit()
В новом окне терминала:

Код: Выделить всё

project_dir> python
>>> import pickle
>>> from package_b.module_b import B
>>> with open("b.pickle", "rb") as f:
...     b_obj = pickle.load(f)
...
>>> b_obj.a.name
'A'
Как Pickle может создать объект A, если я никуда не импортировал модуль_a?
EDIT: Когда я изменяю A, чтобы иметь метод получения для атрибута имени класса:

Код: Выделить всё

class A:
name = "A"

@classmethod
def get_name(cls):
return cls.name
Следующий эксперимент все еще работает:

Код: Выделить всё

project_dir> python
>>> import pickle
>>> from package_a.module_a import A
>>> from package_b.module_b import B
>>> b_obj = B()
>>> b_obj.a = A()
>>> b_obj.a.get_name()
'A'
>>> b_obj.a.__class__

>>> with open("b.pickle", "wb") as f:
...     pickle.dump(b_obj, f)
...
>>> exit()

Код: Выделить всё

>>> import pickle
>>> from package_b.module_b import B
>>> with open("b.pickle", "rb") as f:
...     b_obj = pickle.load(f)
...
>>> b_obj.a.get_name()
'A'
>>> b_obj.a.__class__

Это противоречит документации по травлению, в которой говорится, что

...когда экземпляры классов маринуются, их код и данные класса не маринуются вместе с ними. Консервируются только данные экземпляра.

Что именно здесь происходит под капотом?

Подробнее здесь: https://stackoverflow.com/questions/790 ... rom-a-file

Вернуться в «Python»