Python 如何pickle NotImplementedType

Python 如何pickle NotImplementedType,python,python-2.7,pickle,deep-copy,Python,Python 2.7,Pickle,Deep Copy,如何在Python中添加对酸洗传统上不可酸洗类型的支持 我需要pickle一个复杂的对象,它包含对类NotImplementedType的引用。该类是第三方的,因此我无法重写其\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 我不完全清楚为什么Pickle不能序列化NotImplementedType。我肯定有一些愚蠢的教条理由,我

如何在Python中添加对酸洗传统上不可酸洗类型的支持

我需要pickle一个复杂的对象,它包含对类
NotImplementedType
的引用。该类是第三方的,因此我无法重写其
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

我不完全清楚为什么Pickle不能序列化NotImplementedType。我肯定有一些愚蠢的教条理由,我不在乎。事实上,这个类永远不会更改,并且不包含任何状态,因此它应该是可序列化的。果然,可以很好地序列化这个类

因此,我尝试为
NotImplementedType
实现一个自定义处理程序,它使用类似dill的代码:

copy_reg.pickle(NotImplementedType,
   lambda code: (dill.loads, (dill.dumps(code),)),
   dill.loads)
但是,尝试深度复制我的对象会引发异常:

'NoneType' object has no attribute 'update'

来自
/usr/lib/python2.7/copy.py
中的第347行。深入研究这段代码表明,copy_reg/deepcopy/pickle模块希望序列化和反序列化实例,而不是类的引用,它抛出此异常是因为它试图实例化
NotImplementedType
,而不是只查找类引用。对此有什么解决办法吗?

所讨论的类实际上不太可能包含
NotImplementedType
;相反,它可能是pickling
NotImplemented
,而
NotImplemented
的缩减函数正试图根据其类型对其进行pickle,但是
NotImplementedType
不会直接公开(您只能通过
type(NotImplemented)
获得它),因此,尝试创建可查找
NotImplementedType
的限定名称失败。这在Python3(移动的另一个参数)中是固定的,但在Python2中也很容易固定,因为为
NotImplementedType
定义一个普通的
copy\u reg
处理程序将确保
NotImplemented
在不引用自身类型的情况下被pickle

实现这一点的简单方法是让reducer函数返回字符串naming
NotImplemented
,然后在取消勾选时将其作为全局查找。方便地说,这意味着您不需要定义任何帮助器方法(可能不存在于取消勾选端):

您根本不定义构造函数(第三个
copy\u reg.pickle
参数);pickle将包含重新创建
NotImplemented
所需的所有信息,而不依赖于取消pickle端,返回
NotImplemented
,而不尝试序列化
NotImplementedType
函数显式允许返回字符串的函数。如果是字符串,它将使用该字符串作为“查找”的名称(另请参见):

这将允许复制(和pickle)
NotImplemented

import copy

>>> type(copy.deepcopy(NotImplemented))              # still a NotImplementedType object
NotImplementedType

>>> copy.deepcopy(NotImplemented) is NotImplemented  # and still the same object!
True

我刚刚在Python3.6中尝试了pickling NotImplementedType,它就这样发生了,没有任何错误。(NotImplementedType获得为
ref=type(NotImplemented)
),另一方面,我可以确认您在Python2.7中的错误。您是否尝试过使用协议2显式酸洗?2.7上的默认pickle协议是0,并且它缺乏对新样式类的许多特性的支持(即使它可以工作,在时间和空间上都非常低效)。协议2本机支持新样式的类,它更快、更小,并且可以处理协议0/1根本无法处理的许多事情。啊,没关系。我以为
NotImplementedType
是一些特殊的第三方东西,看起来它只是
type(NotImplemented)
。它不适用于Py2上的任何协议,也适用于Py3上的所有协议,在Py3上它发展了一个专门的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。在重读时捕获字符串行为,以确保没有错过更好的解决方案。忽略这一点,误读:你的演示代码是错误的;它应该生成
NotImplementedType
,而不是
NotImplementedType
@ShadowRanger,我在
deepcopy
的返回值上使用了
type
,所以它应该是
NotImplementedType
,但我还添加了另一个例子,即使在deepcopy之后它仍然是相同的“全局性的”。啊,哇。这就是我略读的结果。是的,没错。这确实假设第三方类实际上没有在实例中存储
NotImplementedType
本身,但是如果它这样做的话会非常奇怪。是的,我刚刚检查了CPython源代码。在Py2中,没有为
未实现
(it)定义特殊的
\uuuuuuuuuuuuuuuuuuuuuuuuuuu
,但在Py3中,它与我的
复制
解决方案完全相同。因此,
copy\u reg
方法与Py3完全相同。使用此解决方案,我仍然会得到
AttributeError:“非类型”对象没有属性“更新”
@IvanCastellanos:你得到了什么错误?OP甚至没有提供代码示例,因此您可以运行任何东西。我可以告诉您,在我的回答中运行确切的代码(导入
copy_reg
后)会使
NotImplemented
在Python 2.7上可以进行往返拾取(而不执行注册会使其与
TypeError一起消亡:无法pickle NotImplementedType对象
),但是我猜不出你的代码有什么问题。测试非常简单(
pickle.load(pickle.dumps(NotImplemented))
,换成
cPickle进行加速测试)。
import copy_reg
copy_reg.pickle(type(NotImplemented), lambda x: 'NotImplemented')
import copy

>>> type(copy.deepcopy(NotImplemented))              # still a NotImplementedType object
NotImplementedType

>>> copy.deepcopy(NotImplemented) is NotImplemented  # and still the same object!
True