创建python对象时报错:
TypeError: cannot pickle 'module' object
原因:
很大可能是类成员错误的使用了第三方包(别名)等,具体排查方法可参考:
import redis
import pickle
from pprint import pformat as pf
def pickle_trick(obj, max_depth=10):
output = {}
if max_depth <= 0:
return output
try:
pickle.dumps(obj)
except (pickle.PicklingError, TypeError) as e:
failing_children = []
if hasattr(obj, "__dict__"):
for k, v in obj.__dict__.items():
result = pickle_trick(v, max_depth=max_depth - 1)
if result:
failing_children.append(result)
output = {
"fail": obj,
"err": e,
"depth": max_depth,
"failing_children": failing_children
}
return output
if __name__ == "__main__":
r = redis.Redis()
print(pf(pickle_trick(r)))
另外附上说明:
What can be pickled and unpickled?
The following types can be pickled:
None, True, and False
integers, floating point numbers, complex numbers
strings, bytes, bytearrays
tuples, lists, sets, and dictionaries containing only picklable objects
functions defined at the top level of a module (using def, not lambda)
built-in functions defined at the top level of a module
classes that are defined at the top level of a module
instances of such classes whose
__dict__
or the result of calling__getstate__()
is picklable (see section Pickling Class Instances for details).
As you can see, modules are not part of this list. Note, that this is also true when using deepcopy
and not only for the pickle
module, as stated in the documentation of deepcopy
:
This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.
A possible workaround is using the @property
decorator instead of an attribute. For example, this should work:
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)
参考资料: