2009-09-11 10 views
16

Dies ist der Fehler, den ich heute um http://filmaster.com bekommen habe:>> filteraster.com:PicklingError: Kann nicht <Klasse> Dezimal Dezimal '>: Es ist nicht das gleiche Objekt wie Dezimal Dezimal

PicklingError: Can't pickle : it's not the same object as decimal.Decimal

Was bedeutet das genau es nicht viel Sinn zu machen scheint ... Es scheint mit django Caching verbunden werden Sie die ganze Zurückverfolgungs hier sehen können:.

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 : it's not the same object as decimal.Decimal

Und der Quellcode für Filmaster kann von hier heruntergeladen werden: bitbucket.org/filmaster/filmaster-test

Jede Hilfe wird sehr geschätzt.

+0

Ich habe einen ähnlichen Fehler nach dem Schreiben einer fehlerhaften __getstate__ Methode für ein Objekt, um seine Pickle Verhalten zu ändern. Nicht sicher, was das Problem ist, aber nach irgendwelchen von denen überprüfen. – partofthething

+0

Ich habe das auch mit Klassen-Dekoratoren gesehen, speziell die six.add_metaclass – dbn

Antwort

16

Eine Besonderheit von Pickle ist, dass die Art, wie Sie eine Klasse importieren, bevor Sie eine seiner Instanzen pickle, das eingelegte Objekt subtil ändern kann. Pickle erfordert, dass Sie das Objekt identisch importiert haben, bevor Sie es in Essig einlegen und bevor Sie es aufheben.

So zum Beispiel:

from a.b import c 
C = c() 
pickler.dump(C) 

ein leicht unterschiedliches Objekt machen (manchmal) zu:

from a import b 
C = b.c() 
pickler.dump(C) 

Versuchen Sie, mit Ihren Importen Hantieren, könnte es das Problem zu beheben.

+8

. Wie kommt es also, dass dieses Beizproblem nur einmal in Tausenden von Anfragen auftritt und normalerweise funktioniert es gut? – michuk

2

Haben Sie irgendwie reload(decimal), oder Monkeypatch das Dezimal-Modul, um die Decimal-Klasse zu ändern? Dies sind die zwei Dinge, die am ehesten zu einem solchen Problem führen.

+0

Nichts, nichts in dieser Art. Ich importiere nur die Dezimalklasse. – michuk

17

Ich habe diesen Fehler beim Ausführen in einem Jupyter-Notebook. Ich denke, das Problem war, dass ich %load_ext autoreloadautoreload 2 verwendet habe. Neustart des Kernels und erneute Ausführung lösten das Problem.

+0

Es scheint, dass das Ändern einer Klassenmethode die Ursache des Problems ist. Meine Vermutung ist, dass das "Autoreload" keine Definition aktualisiert, die woanders gespeichert wurde. Neustart würde es beheben, da die neuere Definition an beiden Orten geladen wird. – theindigamer

2

Es kann Probleme beim Starten eines Prozesses mit multiprocessing durch den Aufruf __init__ geben. Hier ist eine Demo:

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)) 

Jetzt, mit dem obigen Code, wenn wir dies auszuführen:

if __name__ == '__main__': 
    t = ProcessInitTest(spawn=True) 
    t.start_process_fail() 
    for i in range(1000): 
     t.do_square(i) 

Wir bekommen diesen Fehler:

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__ 

Und wenn wir es ändern fork zu verwenden anstelle von spawn:

if __name__ == '__main__': 
    t = ProcessInitTest(spawn=False) 
    t.start_process_fail() 
    for i in range(1000): 
     t.do_square(i) 

Wir bekommen diesen Fehler:

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' 

Aber wenn wir nennen das start_process Methode, die nicht __init__ im mp.Process Ziel nicht nennen, wie folgt aus:

if __name__ == '__main__': 
    t = ProcessInitTest(spawn=False) 
    t.start_process() 
    for i in range(1000): 
     t.do_square(i) 

Es funktioniert wie erwartet (ob wir Verwenden Sie spawn oder fork).

0

Ich kann nicht erklären, warum dies entweder versagt, aber meine eigene Lösung dieses Problem zu beheben war alles von meinem Code zu ändern

tun
from point import Point 

zu

import point 

dieser Änderung und hat funktioniert. Ich würde gerne wissen, warum ... hth