PicklingError: 无法序列化 <class 'decimal.Decimal'>: 不是与 decimal.Decimal 相同的对象
今天我在<a href="http://filmaster.com">filmaster.com</a>上遇到了这个错误:
PicklingError: Can't pickle <class 'decimal.Decimal'>: it's not the same object as decimal.Decimal
这到底是什么意思呢?感觉有点难以理解……
这似乎和django的缓存有关。你可以在这里看到完整的错误追踪信息:
Traceback (most recent call last): File "/home/filmaster/django-trunk/django/core/handlers/base.py", line 92, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/home/filmaster/film20/film20/core/film_views.py", line 193, in show_film workflow.set_data_for_authenticated_user() File "/home/filmaster/film20/film20/core/film_views.py", line 518, in set_data_for_authenticated_user object_id = self.the_film.parent.id) File "/home/filmaster/film20/film20/core/film_helper.py", line 179, in get_others_ratings set_cache(CACHE_OTHERS_RATINGS, str(object_id) + "_" + str(user_id), userratings) File "/home/filmaster/film20/film20/utils/cache_helper.py", line 80, in set_cache return cache.set(CACHE_MIDDLEWARE_KEY_PREFIX + full_path, result, get_time(cache_string)) File "/home/filmaster/django-trunk/django/core/cache/backends/memcached.py", line 37, in set self._cache.set(smart_str(key), value, timeout or self.default_timeout) File "/usr/lib/python2.5/site-packages/cmemcache.py", line 128, in set val, flags = self._convert(val) File "/usr/lib/python2.5/site-packages/cmemcache.py", line 112, in _convert val = pickle.dumps(val, 2) PicklingError: Can't pickle <class 'decimal.Decimal'>: it's not the same object as decimal.Decimal
Filmaster的源代码可以从这里下载:bitbucket.org/filmaster/filmaster-test
任何帮助都将非常感谢。
16 个回答
29
我将用简单的Python类在Python2.7中演示这个问题:
In [13]: class A: pass
In [14]: class B: pass
In [15]: A
Out[15]: <class __main__.A at 0x7f4089235738>
In [16]: B
Out[16]: <class __main__.B at 0x7f408939eb48>
In [17]: A.__name__ = "B"
In [18]: pickle.dumps(A)
---------------------------------------------------------------------------
PicklingError: Can't pickle <class __main__.B at 0x7f4089235738>: it's not the same object as __main__.B
这个错误出现是因为我们试图保存对象A,但我们把它的名字改成了指向另一个对象“B”。这样一来,pickle就搞不清楚到底要保存哪个对象——是类A还是类B。显然,pickle的开发者很聪明,他们已经对这种情况进行了检查。
解决办法: 检查一下你想要保存的对象是否和其他对象的名字冲突。
我在下面用ipython和ipdb演示了如何调试上面提到的情况:
PicklingError: Can't pickle <class __main__.B at 0x7f4089235738>: it's not the same object as __main__.B
In [19]: debug
> /<path to pickle dir>/pickle.py(789)save_global()
787 raise PicklingError(
788 "Can't pickle %r: it's not the same object as %s.%s" %
--> 789 (obj, module, name))
790
791 if self.proto >= 2:
ipdb> pp (obj, module, name) **<------------- you are trying to dump obj which is class A from the pickle.dumps(A) call.**
(<class __main__.B at 0x7f4089235738>, '__main__', 'B')
ipdb> getattr(sys.modules[module], name) **<------------- this is the conflicting definition in the module (__main__ here) with same name ('B' here).**
<class __main__.B at 0x7f408939eb48>
希望这能帮你省去一些麻烦!再见!!
39
Pickle 有个奇怪的地方,就是在你准备把一个类的实例保存成文件之前,导入这个类的方式可能会影响到保存下来的对象。Pickle 要求你在保存和读取这个对象时,导入的方式必须完全一样。
举个例子:
from a.b import c
C = c()
pickler.dump(C)
这样保存下来的对象(有时候)会和:
from a import b
C = b.c()
pickler.dump(C)
这样保存的对象不太一样。
你可以试着调整一下你的导入方式,可能会解决这个问题。
119
我在使用jupyter notebook的时候遇到了这个错误。我觉得问题出在我用了 %load_ext autoreload
和 autoreload 2
。重启我的内核然后重新运行代码就解决了这个问题。