mar*_*ama 11 python pickle namedtuple python-3.5
为什么我不能腌制一段typing.NamedTuple时间我可以腌制一个collections.namedtuple?我怎么能设法做一个泡菜NamedTuple?
此代码显示了到目前为止我尝试过的内容:
from collections import namedtuple
from typing import NamedTuple
PersonTyping = NamedTuple('PersonTyping', [('firstname',str),('lastname',str)])
PersonCollections = namedtuple('PersonCollections', ['firstname','lastname'])
pt = PersonTyping("John","Smith")
pc = PersonCollections("John","Smith")
import pickle
import traceback
try:
with open('personTyping.pkl', 'wb') as f:
pickle.dump(pt, f)
except:
traceback.print_exc()
try:
with open('personCollections.pkl', 'wb') as f:
pickle.dump(pc, f)
except:
traceback.print_exc()
Run Code Online (Sandbox Code Playgroud)
shell上的输出:
$ python3 prova.py
Traceback (most recent call last):
File "prova.py", line 16, in <module>
pickle.dump(pt, f)
_pickle.PicklingError: Can't pickle <class 'typing.PersonTyping'>: attribute lookup PersonTyping on typing failed
$
Run Code Online (Sandbox Code Playgroud)
这是一个错误。我已经打开了一张票:http : //bugs.python.org/issue25665
问题在于,namedtuple函数在创建类时会__module__通过__name__从调用框架的全局变量中查找属性来设置其属性。在这种情况下,呼叫者为typing.NamedTuple。
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
Run Code Online (Sandbox Code Playgroud)
因此,最终'typing'在这种情况下进行了设置。
>>> type(pt)
<class 'typing.PersonTyping'> # this should be __main__.PersonTyping
>>> type(pc)
<class '__main__.PersonCollections'>
>>> import typing
>>> typing.NamedTuple.__globals__['__name__']
'typing'
Run Code Online (Sandbox Code Playgroud)
固定:
代替此NamedTuple功能,函数应自行设置:
def NamedTuple(typename, fields):
fields = [(n, t) for n, t in fields]
cls = collections.namedtuple(typename, [n for n, t in fields])
cls._field_types = dict(fields)
try:
cls.__module__ = sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return cls
Run Code Online (Sandbox Code Playgroud)
现在,您还可以执行以下操作:
PersonTyping = NamedTuple('PersonTyping', [('firstname',str),('lastname',str)])
PersonTyping.__module__ = __name__
Run Code Online (Sandbox Code Playgroud)