这是我今天在 filmaster.com 上遇到的错误:
PicklingError: 无法 pickle :不一样
对象为十进制。Decimal
这究竟意味着什么?似乎没有多大意义……
它似乎与 django 缓存有关。您可以在这里看到整个回溯:
回溯(最近一次调用):
文件
“/home/filmaster/django-trunk/django/core/handlers/base.py”,
第 92 行,在 get_response 响应 =
回调(请求,*callback_args,
**callback_kwargs)
文件
“/home/filmaster/film20/film20/core/film_views.py”,
show_film 中的第 193 行
工作流.set_data_for_authenticated_user()
文件
“/home/filmaster/film20/film20/core/film_views.py”,
518 行,在
set_data_for_authenticated_user
object_id = self.the_film.parent.id)
文件
“/home/filmaster/film20/film20/core/film_helper.py”,
get_others_ ratings 中的第 179 行
set_cache(CACHE_OTHERS_RATINGS,
str(object_id) + "_" + str(user_id),
用户评分)
文件
“/home/filmaster/film20/film20/utils/cache_helper.py”,
第 80 行,在 set_cache 返回中
缓存.设置(CACHE_MIDDLEWARE_KEY_PREFIX
+ 完整路径、结果、get_time(cache_string))
文件
“/home/filmaster/django-trunk/django/core/cache/backends/memcached.py”,
第 37 行,已设置
self._cache.set(smart_str(key), 值,
超时或 self.default_timeout)
文件
“/usr/lib/python2.5/site-packages/cmemcache.py”,
第 128 行,在 set val 中,flags =
self._convert(val)
文件
“/usr/lib/python2.5/site-packages/cmemcache.py”,
第 112 行,在 _convert val =
pickle.dumps(val, 2)
PicklingError:无法 pickle :不一样
对象为十进制。Decimal
Filmmaster 的源代码可以从这里下载:bitbucket.org/filmaster/filmaster-test
任何帮助将不胜感激。
This is the error I got today at <a href"http://filmaster.com">filmaster.com:
PicklingError: Can't pickle <class
'decimal.Decimal'>: it's not the same
object as decimal.Decimal
What does that exactly mean? It does not seem to be making a lot of sense...
It seems to be connected with django caching. You can see the whole traceback here:
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
And the source code for Filmaster can be downloaded from here: bitbucket.org/filmaster/filmaster-test
Any help will be greatly appreciated.
发布评论
评论(16)
在 jupyter 笔记本中运行时出现此错误。我认为问题是我使用的是
%load_ext autoreload
autoreload 2
。重新启动我的内核并重新运行解决了问题。I got this error when running in an jupyter notebook. I think the problem was that I was using
%load_ext autoreload
autoreload 2
. Restarting my kernel and rerunning solved the problem.Pickle 的一个奇怪之处是,在腌制某个类的实例之前导入类的方式可能会巧妙地更改腌制的对象。 Pickle 要求您在 pickle 之前和 unpickle 之前以相同的方式导入对象。
例如:
会(有时)创建一个略有不同的对象:
尝试摆弄您的导入,它可能会纠正问题。
One oddity of Pickle is that the way you import a class before you pickle one of it's instances can subtly change the pickled object. Pickle requires you to have imported the object identically both before you pickle it and before you unpickle it.
So for example:
will make a subtly different object (sometimes) to:
Try fiddling with your imports, it might correct the problem.
我将用Python2.7中的简单Python类来演示这个问题:
显示此错误是因为我们试图转储A,但因为我们更改了它的名称以引用另一个对象“B”,所以pickle实际上与要转储的对象混淆了- A 或 B 级。显然,泡菜人非常聪明,他们已经检查了这种行为。
解决方案:
检查您尝试转储的对象是否与另一个对象有冲突的名称。
我已经在下面使用 ipython 和 ipdb 演示了上述情况的调试:
我希望这可以避免一些麻烦!再见!
I will demonstrate the problem with simple Python classes in Python2.7:
This error is shown because we are trying to dump A, but because we changed its name to refer to another object "B", pickle is actually confused with which object to dump - class A or B. Apparently, pickle guys are very smart and they have already put a check on this behavior.
Solution:
Check if the object you are trying to dump has conflicting name with another object.
I have demonstrated debugging for the case presented above with ipython and ipdb below:
I hope this saves some headaches! Adios!!
我也无法解释为什么会失败,但我自己解决此问题的解决方案是将我的所有代码从“执行”更改
为
“这一更改”,并且它有效。我很想知道为什么...hth
I can't explain why this is failing either, but my own solution to fix this was to change all my code from doing
to
this one change and it worked. I'd love to know why... hth
您是否以某种方式
重新加载(decimal)
,或者对decimal模块进行了monkeypatch以更改Decimal类?这是最有可能产生此类问题的两件事。Did you somehow
reload(decimal)
, or monkeypatch the decimal module to change the Decimal class? These are the two things most likely to produce such a problem.通过调用
__init__
启动使用multiprocessing
的进程可能会出现问题。这是一个演示:现在,使用上面的代码,如果我们运行:
我们会得到这个错误:
如果我们将其更改为使用
fork
而不是spawn
:我们会得到这个错误:
但是如果我们调用
start_process
方法,该方法不会在mp.Process
目标中调用__init__
,如下所示:预期(无论我们使用
spawn
还是fork
)。There can be issues starting a process with
multiprocessing
by calling__init__
. Here's a demo:Now, with the above code, if we run this:
We get this error:
And if we change it to use
fork
instead ofspawn
:We get this error:
But if we call the
start_process
method, which doesn't call__init__
in themp.Process
target, like this:It works as expected (whether we use
spawn
orfork
).我也遇到了同样的情况
,重新启动内核对我有用
Same happened to me
Restarting the kernel worked for me
由于基于声誉的限制,我无法发表评论,但是 Salim Fahedy 的答案并遵循调试路径设置了我要确定此错误的原因,即使使用
dill
而不是pickle
时也是如此:在底层,
dill
还可以访问dill
的一些功能。在pickle._Pickler.save_global()
中,发生了import
。在我看来,这更像是一种“黑客”而不是真正的解决方案,因为只要您尝试腌制的实例的类不是从该类所在的包的最低级别导入,此方法就会失败。抱歉,解释不好,也许例子更合适:下面的例子会失败:
它失败了,因为虽然你可以使用 solph.Model ,但该类实际上是 oemof.solph.models。例如模型。
save_global()
解析该问题(或将其传递给save_global()
之前的某个函数),但随后从导入
并抛出错误,因为它与Model
oemof.solph.modelsfrom oemof import solph.Model
的导入不同(或类似的东西,我不能 100% 确定其工作原理)。以下示例可行:
它可行,因为现在
Model
对象是从同一位置导入的,pickle._Pickler.save_global()
导入比较对象 (>obj2
) 来自。长话短说:当 pickle 对象时,请确保从尽可能低的级别导入类。
添加:这似乎也适用于存储在要腌制的类实例的属性中的对象。例如,如果
model
有一个属性es
,它本身就是类oemof.solph.energysystems.EnergySystem
的对象,我们需要导入其为:Due to the restrictions based upon reputation I cannot comment, but the answer of Salim Fahedy and following the debugging-path set me up to identify a cause for this error, even when using
dill
instead ofpickle
:Under the hood,
dill
also accesses some functions ofdill
. And inpickle._Pickler.save_global()
there is animport
happening. To me it seems, that this is more of a "hack" than a real solution as this method fails as soon as the class of the instance you are trying to pickle is not imported from the lowest level of the package the class is in. Sorry for the bad explanation, maybe examples are more suitable:The following example would fail:
It fails, because while you can use
solph.Model
, the class actually isoemof.solph.models.Model
for example. Thesave_global()
resolves that (or some function before that which passes it tosave_global()
), but then importsModel
fromoemof.solph.models
and throws an error, because it's not the same import asfrom oemof import solph.Model
(or something like that, I'm not 100% sure about the workings).The following example would work:
It works, because now the
Model
object is imported from the same place, thepickle._Pickler.save_global()
imports the comparison object (obj2
) from.Long story short: When pickling an object, make sure to import the class from the lowest possible level.
Addition: This also seems to apply to objects stored in the attributes of the class-instance you want to pickle. If for example
model
had an attributees
that itself is an object of the classoemof.solph.energysystems.EnergySystem
, we would need to import it as:我在调试(Spyder)时遇到了同样的问题。如果运行程序一切正常。但是,如果我开始调试,我就会遇到 picklingError。
但是,一旦我在每个文件的运行配置中选择在专用控制台中执行选项(快捷键:ctrl+F6),一切都会按预期正常工作。我不知道它具体是如何适应的。
注意:在我的脚本中,我有很多导入,就像
我的基本理解是,由于星号(*),我得到了这个 picklingError。
I had same problem while debugging (Spyder). Everything worked normally if run the program. But, if I start to debug I faced the picklingError.
But, once I chose the option Execute in dedicated console in Run configuration per file (short-cut: ctrl+F6) everything worked normally as expected. I do not know exactly how it is adapting.
Note: In my script I have many imports like
My basic understanding was, because of star (*) I was getting this picklingError.
我的问题是我在一个文件中定义了两次同名的函数。所以我猜它对要腌制哪一个感到困惑。
My issue was that I had a function with the same name defined twice in a file. So I guess it was confused about which one it was trying to pickle.
我遇到了一个尚未有人提及的问题。我有一个带有
__init__
文件的包,除其他外,它执行以下操作:然后我的顶级代码说:
问题在于,在我的顶级代码中,类型似乎是
mypkg.cls
,但它实际上是mypkg.mymodule.cls
。使用完整路径:避免错误。
I had a problem that no one has mentioned yet. I have a package with a
__init__
file that does, among other things:Then my top-level code says:
The problem with this is that in my top-level code, the type appears to be
mypkg.cls
, but it's actuallymypkg.mymodule.cls
. Using the full path:avoids the error.
我在 Spyder 中也遇到了同样的错误。就我而言,结果很简单。我在一个名为“Class”的文件中定义了一个名为“Class”的类。我将定义中的类名称更改为“Class_obj”。
pickle.dump(Class_obj,fileh)
有效,但pickle.dump(Class,fileh)
在保存在名为“Class”的文件中时无效。I had the same error in Spyder. Turned out to be simple in my case. I defined a class named "Class" in a file also named "Class". I changed the name of the class in the definition to "Class_obj".
pickle.dump(Class_obj,fileh)
works, butpickle.dump(Class,fileh)
does not when its saved in a file named "Class".这个神奇的功能解决了上述错误,但对我来说,它结果是另一个突然出现的错误“权限被拒绝”。但是,我想这可能会帮助某人找到解决方案,所以我仍然发布该功能:
This miraculous function solves the mentioned error, but for me it turned out to another error 'permission denied' which comes out of the blue. However, I guess it might help someone find a solution so I am still posting the function:
建立在这些两个之上a> 答案:如果您收到
PicklingError: Can't pickle: it's not the same object as foo.Bar
形式的错误,请尝试替换Bar
与foo.Bar
。您可以使用此代码片段来尝试调试出现问题的地方:
Building on these two answers: if you get an error of the form
PicklingError: Can't pickle <class 'foo.Bar'>: it's not the same object as foo.Bar
, try replacingBar
withfoo.Bar
.You can use this snippet to try and debug where things go wrong:
当使用带有装饰器的工厂模式来生成我的对象时,我收到此错误:
这按预期工作并产生
但是,我实现了
register< /code> 装饰器不正确;我应该这样写:
我缺少的关键是返回装饰器中的原始类,这表明了这个错误。对于这样的类,返回的对象是实际在模块级别保存的类,在我的例子中是 None 。我一开始没有注意到这一点,因为工厂已经缓存了该类,并且我所有的代码都使用工厂来生成这些对象。由于
pickle
直接使用sys.modules
,因此只有当我尝试从损坏的工厂中 pickle 一个对象时才会出现此错误。I got this error when using a factory pattern with a decorator to produce my objects:
This works as expected and yields
<class '__main__.SomeClass'>
However, I implemented the
register
decorator incorrectly; I should have written it like so:The key that I was missing was to return the original class in the decorator, which manifested with this error. In the case of a class like this, the returned object is the class that actually gets saved at the module level, which in my case was None. I didn't notice this at first, because the factory has cached the class, and all of my code was using the factory to generate these objects. Since
pickle
usessys.modules
directly, this error only popped up when I tried to pickle one of the objects from the broken factory.有同样的问题,我的问题来自装饰器,更具体地说是@lru_cache。
我建议前往 Pickle 和装饰类 (PicklingError: not相同的对象)
Had the same problem, my problem came from a decorator, more specifically @lru_cache.
I'd recommend heading to Pickle and decorated classes (PicklingError: not the same object)