如何调试调用Python';是否针对自定义类型设置s copy.deepcopy()?

如何调试调用Python';是否针对自定义类型设置s copy.deepcopy()?,python,deep-copy,Python,Deep Copy,在我的代码中,我试图使用copy.deepcopy复制一个类的实例。问题在于,在某些情况下,它会出现以下错误: TypeError: 'object.__new__(NotImplementedType) is not safe, use NotImplementedType.__new__()' 经过大量挖掘,我发现我能够使用以下代码重现错误: import copy copy.deepcopy(__builtins__) 问题似乎是,在某个时刻,它试图复制NotImplementedT

在我的代码中,我试图使用
copy.deepcopy
复制一个类的实例。问题在于,在某些情况下,它会出现以下错误:

TypeError: 'object.__new__(NotImplementedType) is not safe, use NotImplementedType.__new__()'
经过大量挖掘,我发现我能够使用以下代码重现错误:

import copy
copy.deepcopy(__builtins__) 
问题似乎是,在某个时刻,它试图复制
NotImplementedType
builtin。问题是它为什么这样做?我没有在我的课堂上重写
\uuuuuu deepcopy\uuuuu
,而且这种情况并非总是发生。有没有人有任何技巧来追踪制作这种类型副本的请求来自哪里


我已经在
copy
模块本身中添加了一些调试代码,以确保这是正在发生的事情,但是问题发生的点是递归堆栈,很难充分利用我看到的内容。

您可以覆盖u deepcopy_u_u_u__方法:()

为了让类定义自己的复制实现,它可以定义特殊的方法\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。调用前者实现浅层复制操作;不传递其他参数。调用后者来实现深度复制操作;它传递了一个参数,即备忘录字典。如果\uuuu deepcopy\uuuuu()实现需要对组件进行深度复制,它应该调用deepcopy()函数,将组件作为第一个参数,将备忘录字典作为第二个参数


否则,您可以将模块保存在全局列表或其他内容中。

最后,我在
副本
源代码中进行了一些挖掘,并提出了以下解决方案:

from copy import deepcopy, _deepcopy_dispatch
from types import ModuleType

class MyType(object):

    def __init__(self):
        self.module = __builtins__

    def copy(self):
        ''' Patch the deepcopy dispatcher to pass modules back unchanged '''
        _deepcopy_dispatch[ModuleType] = lambda x, m: x
        result = deepcopy(self)
        del _deepcopy_dispatch[ModuleType]
        return result

MyType().copy()
我意识到这使用了一个私有API,但我找不到另一个干净的方法来实现同样的事情。我在网上做了一个测试,发现其他人使用了相同的API,没有任何麻烦。如果将来情况发生变化,我将承担责任

我也知道这不是线程安全的(如果一个线程需要旧的行为,而我在另一个线程上复制,我会被拧紧),但这对我来说不是一个问题


希望这能在某些方面帮助其他人。

您可以使用复制模块支持的重写类的deepcopy行为,该类包含指向模块的指针,如上所述。特别是,您可以为该类定义
\uuu getstate\uu
\uu setstate\uu
。例如:

>>> class MyClass:
...     def __getstate__(self):
...         state = self.__dict__.copy()
...         del state['some_module']
...         return state
...     def __setstate__(self, state):
...         self.__dict__.update(state)
...         self.some_module = some_module

你的实例引用的是什么类型的东西?@Matt:这些实例包含configobj实例和其他东西(其他东西是标准列表和dict等)。好的,问题似乎是其中一个成员是包含模块引用的dict。所以现在的问题似乎是,当遇到某些类型时,如何让deepcopy停止,而不尝试复制它们(在我的例子中是模块和类)。有什么线索吗?我刚刚注意到你说有问题的模块是dict的一个成员。如果有一个(单个)对象拥有该dict,那么该对象可以定义定制的getstate/setstate来适当地损坏dict。如果dict被多个对象共享,那么您可能会使用monkey补丁方法卡住。(或者稍微重构一下代码。)