これは本日http://filmaster.com "> filmaster.comで発生したエラーです。
PicklingError:ピクルできません:decimal.Decimalと同じオブジェクトではありません
それはどういう意味ですか?それは多くの意味をなさないようです...それはDjangoキャッシングと接続されているようです。ここでトレースバック全体を見ることができます:
トレースバック(最新の呼び出しが最後):
ファイル「/home/filmaster/Django-trunk/Django/core/handlers/base.py」の92行目のget_responseレスポンス= callback(request、* callback_args、** callback_kwargs)
Show_filmのファイル「/home/filmaster/film20/film20/core/film_views.py」、193行目
workflow.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)Get_others_ratingsのファイル「/home/filmaster/film20/film20/core/film_helper.py」の179行目
set_cache(CACHE_OTHERS_RATINGS、str(object_id)+ "_" + str(user_id)、userratings)ファイル "/home/filmaster/film20/film20/utils/cache_helper.py"、80行、set_cacheでcache.set(CACHE_MIDDLEWARE_KEY_PREFIX + full_path、result、get_time(cache_string))を返す
ファイル「/home/filmaster/Django-trunk/Django/core/cache/backends/memcached.py」、37行目、セット
self._cache.set(smart_str(key)、value、timeout or 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:ピクルできません:decimal.Decimalと同じオブジェクトではありません
Filmasterのソースコードは、こちらからダウンロードできます。 bitbucket.org/filmaster/filmaster-test
どんな助けでも大歓迎です。
Jupyterノートブックで実行すると、このエラーが発生しました。問題は、私が%load_ext autoreload
autoreload 2
。カーネルを再起動して再実行すると問題は解決しました。
Pickleの奇妙な点の1つは、クラスのインスタンスの1つをpickleする前にクラスをインポートする方法で、pickleされたオブジェクトを微妙に変更できることです。ピクルでは、ピクルする前とピクルする前に、オブジェクトを同じようにインポートする必要があります。
だから例えば:
from a.b import c
C = c()
pickler.dump(C)
微妙に異なるオブジェクトを(時々)作成します:
from a import b
C = b.c()
pickler.dump(C)
インポートをいじってみてください。問題が修正される可能性があります。
簡単な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。彼らはすでにこの振る舞いをチェックしています。
解決策:ダンプしようとしているオブジェクトの名前が別のオブジェクトと競合していないかどうかを確認します。
私は上記のケースのデバッグを以下の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>
これが頭痛の種を救ってくれることを願っています!アディオス!!
これも失敗している理由を説明することはできませんが、これを修正するための私の独自の解決策は、すべてのコードを変更することでした
from point import Point
に
import point
この1つの変更とそれが機能しました。理由を教えてください。
__init__
を呼び出すと、multiprocessing
でプロセスを開始するときに問題が発生する可能性があります。ここにデモがあります:
import multiprocessing as mp
class SubProcClass:
def __init__(self, pipe, startloop=False):
self.pipe = pipe
if startloop:
self.do_loop()
def do_loop(self):
while True:
req = self.pipe.recv()
self.pipe.send(req * req)
class ProcessInitTest:
def __init__(self, spawn=False):
if spawn:
mp.set_start_method('spawn')
(self.msg_pipe_child, self.msg_pipe_parent) = mp.Pipe(duplex=True)
def start_process(self):
subproc = SubProcClass(self.msg_pipe_child)
self.trig_proc = mp.Process(target=subproc.do_loop, args=())
self.trig_proc.daemon = True
self.trig_proc.start()
def start_process_fail(self):
self.trig_proc = mp.Process(target=SubProcClass.__init__, args=(self.msg_pipe_child,))
self.trig_proc.daemon = True
self.trig_proc.start()
def do_square(self, num):
# Note: this is an synchronous usage of mp,
# which doesn't make sense. But this is just for demo
self.msg_pipe_parent.send(num)
msg = self.msg_pipe_parent.recv()
print('{}^2 = {}'.format(num, msg))
さて、上記のコードで、これを実行すると:
if __name__ == '__main__':
t = ProcessInitTest(spawn=True)
t.start_process_fail()
for i in range(1000):
t.do_square(i)
次のエラーが発生します。
Traceback (most recent call last):
File "start_class_process1.py", line 40, in <module>
t.start_process_fail()
File "start_class_process1.py", line 29, in start_process_fail
self.trig_proc.start()
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/process.py", line 105, in start
self._popen = self._Popen(self)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/context.py", line 212, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/context.py", line 274, in _Popen
return Popen(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/popen_spawn_posix.py", line 33, in __init__
super().__init__(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/popen_fork.py", line 21, in __init__
self._launch(process_obj)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/popen_spawn_posix.py", line 48, in _launch
reduction.dump(process_obj, fp)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/reduction.py", line 59, in dump
ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function SubProcClass.__init__ at 0x10073e510>: it's not the same object as __main__.__init__
そして、fork
の代わりにspawn
を使用するように変更した場合:
if __name__ == '__main__':
t = ProcessInitTest(spawn=False)
t.start_process_fail()
for i in range(1000):
t.do_square(i)
次のエラーが発生します。
Process Process-1:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/process.py", line 254, in _bootstrap
self.run()
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
TypeError: __init__() missing 1 required positional argument: 'pipe'
しかし、次のようにstart_process
メソッドを呼び出すと、__init__
ターゲットのmp.Process
は呼び出されません。
if __name__ == '__main__':
t = ProcessInitTest(spawn=False)
t.start_process()
for i in range(1000):
t.do_square(i)
期待どおりに動作します(spawn
またはfork
を使用しているかどうか)。
どういうわけかreload(decimal)
、またはDecimalクラスを変更するためにdecimalモジュールをモンキーパッチしましたか?これらは、このような問題を引き起こす可能性が最も高い2つのものです。
私の問題は、同じ名前の関数がファイルで2回定義されていることでした。だから、どれを漬けようとしたのか混乱していたと思います。
同じことが私にも起こりました
カーネルを再起動するとうまくいきました
デバッグ中に同じ問題が発生しました(Spyder)。プログラムを実行すると、すべてが正常に機能しました。しかし、デバッグを開始すると、picklingErrorに直面しました。
しかし、オプション専用コンソールで実行をファイルごとの実行構成(ショートカット:ctrl + F6)で選択すると、すべて正常に機能しました。それがどのように適応しているかは正確にはわかりません。
注:私のスクリプトでは、次のような多くのインポートがあります
from PyQt5.QtWidgets import *
from PyQt5.Qt import *
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import os, sys, re, math
私の基本的な理解は、スター(*)のため、このpicklingErrorを受け取っていたということです。