问题
I'm trying to pickle a big class and getting
TypeError: can't pickle module objects
despite looking around the web, I can't exactly figure out what this means. and I'm not sure which module object is causing the trouble. is there a way to find the culprit? the stack trace doesn't seem to indicate anything.
回答1:
I can reproduce the error message this way:
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
Do you have a class attribute that references a module?
回答2:
Python's inability to pickle module objects is the real problem. Is there a good reason? I don't think so. Having module objects unpicklable contributes to the frailty of python as a parallel / asynchronous language. If you want to pickle module objects, or almost anything in python, then use 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
>>>
Get dill here: https://github.com/uqfoundation/dill
回答3:
According to the documentation:
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():
return np
foo = Foo()
with open('test.out', 'wb') as f:
pickle.dump(foo, f)
来源:https://stackoverflow.com/questions/2790828/python-cant-pickle-module-objects-error