Python:can';t pickle模块对象错误
我想上一个大班,然后 TypeError:无法pickle模块对象Python:can';t pickle模块对象错误,python,pickle,Python,Pickle,我想上一个大班,然后 TypeError:无法pickle模块对象 尽管环顾了一下网络,我还是不能确切地理解这意味着什么。我不确定是哪个模块对象引起了问题。有办法找到罪犯吗?堆栈跟踪似乎没有任何指示。我可以通过以下方式再现错误消息: import cPickle class Foo(object): def __init__(self): self.mod=cPickle foo=Foo() with file('/tmp/test.out', 'w') as f:
尽管环顾了一下网络,我还是不能确切地理解这意味着什么。我不确定是哪个
模块对象
引起了问题。有办法找到罪犯吗?堆栈跟踪似乎没有任何指示。我可以通过以下方式再现错误消息:
import cPickle
class Foo(object):
def __init__(self):
self.mod=cPickle
foo=Foo()
with file('/tmp/test.out', 'w') as f:
cPickle.dump(foo, f)
# TypeError: can't pickle module objects
您是否有引用模块的class属性?Python无法pickle模块对象是真正的问题。有充分的理由吗?我不这么认为。让模块对象不可拼接会导致python作为并行/异步语言的脆弱性。如果您想要pickle模块对象,或者python中的几乎任何东西,那么使用
dill
Python 3.2.5 (default, May 19 2013, 14:25:55)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> import os
>>> dill.dumps(os)
b'\x80\x03cdill.dill\n_import_module\nq\x00X\x02\x00\x00\x00osq\x01\x85q\x02Rq\x03.'
>>>
>>>
>>> # and for parlor tricks...
>>> class Foo(object):
... x = 100
... def __call__(self, f):
... def bar(y):
... return f(self.x) + y
... return bar
...
>>> @Foo()
... def do_thing(x):
... return x
...
>>> do_thing(3)
103
>>> dill.loads(dill.dumps(do_thing))(3)
103
>>>
获取dill
here:根据文档:
什么可以腌制和不腌制?
可以对以下类型进行酸洗:
- 没有,真的,假的
- 整数、浮点数、复数
- 字符串、字节、字节数组
- 仅包含可拾取对象的元组、列表、集和字典
- 在模块顶层定义的函数(使用def,而不是lambda)
- 在模块顶层定义的内置函数
- 在模块顶层定义的类
- 类的实例,这些类的
\uuuuu dict\uuuu
或调用\uuuuu getstate\uuuuuu()
的结果是可pickle的(有关详细信息,请参阅Pickling Class instances一节)
如您所见,模块不在此列表中。请注意,这在使用deepcopy
时也是正确的,并且不仅仅适用于pickle
模块,如deepcopy
的文档中所述:
此模块不复制诸如模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口、数组或任何类似类型的类型。它通过原封不动地返回原始对象来“复制”函数和类(浅层和深层);这与pickle模块处理这些数据的方式兼容
一种可能的解决方法是使用@属性
装饰器而不是属性。
例如,这应该起作用:
import numpy as np
import pickle
class Foo():
@property
def module(self):
return np
foo = Foo()
with open('test.out', 'wb') as f:
pickle.dump(foo, f)
递归查找Pickle故障
灵感来自wump
的评论:
下面是一些帮助我递归找到罪魁祸首的快速代码
它检查有问题的物体,看它是否不能酸洗
然后迭代尝试在\uuu dict\uuu
中pickle键,返回仅失败pickle的列表
代码片段
导入pickle
def酸洗技巧(obj,最大深度=10):
输出={}
如果是最大深度,
.........
“ZSCORE”:},
“失败的\u子项”:[]}]}
根本原因-Redis无法pickle\u thread.lock
在我的例子中,创建我保存为对象属性的Redis
实例破坏了pickle
当您创建Redis
的实例时,它还会创建线程的连接池
,并且线程锁不能被pickle
我必须在multiprocessing.Process
中创建并清理Redis
,然后才能对其进行酸洗
测试
在我的例子中,我试图腌制的类,必须能够腌制。因此,我添加了一个单元测试,用于创建类的实例并对其进行pickle。这样,如果有人修改该类,使其不能被pickle,从而破坏了它在多处理(和pyspark)中使用的能力,我们将立即检测该回归并知道
def test_can_pickle():
#给定
obj=myclassthatsmustpickle()
#什么时候
pkl=pickle.dumps(obj)
#如果不再正确酸洗,此测试将抛出错误
看不到代码就很难分辨。+1。这是我见过的唯一有意义的方法(引用模块),但我不确定如何找到它。(这节课不是我自己写的,它有3500行长。)你知道我如何找到引用吗?谢谢我唯一想到的是递归下降。。对对象执行dir(…),并尝试分别pickle每个属性。取给出错误的一个,重复相同的操作,直到找到模块对象。