Раньше сегодня у меня возникли проблемы с попыткой рассортировать экземпляр namedtuple. Как проверка работоспособности, я попробовал запустить код, который был отправлен in another answer. Вот она, упрощена немного больше:Понимание проблемы с именем именованным именем и рассолом в Python
from collections import namedtuple
import pickle
P = namedtuple("P", "one two three four")
def pickle_test():
abe = P("abraham", "lincoln", "vampire", "hunter")
f = open('abe.pickle', 'w')
pickle.dump(abe, f)
f.close()
pickle_test()
Затем я изменил две строки этого использовать мой названный кортеж:
from collections import namedtuple
import pickle
P = namedtuple("my_typename", "A B C")
def pickle_test():
abe = P("ONE", "TWO", "THREE")
f = open('abe.pickle', 'w')
pickle.dump(abe, f)
f.close()
pickle_test()
Однако это дало мне ошибку
File "/path/to/anaconda/lib/python2.7/pickle.py", line 748, in save_global
(obj, module, name))
pickle.PicklingError: Can't pickle <class '__main__.my_typename'>: it's not found as __main__.my_typename
т.е. модуль Pickle ищет my_typename
. Я изменил линию P = namedtuple("my_typename", "A B C")
на P = namedtuple("P", "A B C")
, и это сработало.
Я смотрел на источник namedtuple.py
и в итоге мы имеем то, что выглядит уместно, но я не совсем понимаю, что происходит:
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example) or sys._getframe is not
# defined for arguments greater than 0 (IronPython).
try:
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return result
Так что мой вопрос, что именно происходит? Почему аргумент typename
должен соответствовать названию фабрики, чтобы это работало?
Благодарим вас за «альтернативный» способ. Работает как шарм. – Vor