PicklingError: Невозможно засечь <class 'decimal.Decimal'>: это не тот же объект, что и decimal.Decimal - PullRequest
28 голосов
/ 11 сентября 2009

Это ошибка, которую я получил сегодня в http://filmaster.com">filmaster.com:

PicklingError: Не могу засолить: это не то же самое объект как десятичный. десятичный

Что это значит? Кажется, это не имеет большого смысла ... Похоже, это связано с кэшированием Django. Вы можете увидеть всю трассировку здесь:

Traceback (последний вызов был последним):

Файл "/Home/filmaster/django-trunk/django/core/handlers/base.py", строка 92, в ответе get_response = обратный вызов (запрос, * callback_args, ** callback_kwargs)

Файл "/Home/filmaster/film20/film20/core/film_views.py", строка 193, в show_film
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)

Файл "/Home/filmaster/film20/film20/core/film_helper.py", строка 179, в get_others_ratings
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, результат, get_time (cache_string))

Файл "/Home/filmaster/django-trunk/django/core/cache/backends/memcached.py", линия 37, в комплекте
self._cache.set (smart_str (ключ), значение, timeout или self.default_timeout)

Файл "/Usr/lib/python2.5/site-packages/cmemcache.py", строка 128, в заданном val, flags = self._convert (значение)

Файл "/Usr/lib/python2.5/site-packages/cmemcache.py", строка 112, в _convert val = pickle.dumps (val, 2)

PicklingError: Не могу засолить: это не то же самое объект как десятичный. десятичный

А исходный код для Filmaster можно скачать здесь: bitbucket.org / filmaster / filmaster-test

Любая помощь будет принята с благодарностью.

Ответы [ 6 ]

43 голосов
/ 24 июля 2016

Я получил эту ошибку при работе в ноутбуке Jupyter. Я думаю, проблема была в том, что я использовал %load_ext autoreload autoreload 2. Перезапуск моего ядра и повторный запуск решили проблему.

20 голосов
/ 12 сентября 2009

Одна странность Pickle заключается в том, что способ импорта класса перед тем, как вы выберете один из его экземпляров, может слегка изменить протравленный объект. Pickle требует, чтобы вы импортировали объект идентично как до того, как вы это сделаете, так и до того, как вы его удалите.

Так, например:

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

сделает немного другой объект (иногда):

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

Попробуйте поиграть с импортом, это может решить проблему.

3 голосов
/ 20 декабря 2018

Я продемонстрирую проблему с простыми классами 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>

Надеюсь, это избавит от головной боли! Adios !!

3 голосов
/ 24 декабря 2017

Я тоже не могу объяснить, почему это не сработало, но мое собственное решение исправить это состояло в том, чтобы поменять весь мой код с выполнения

from point import Point

до

import point

это одно изменение, и оно сработало. Я хотел бы знать, почему ... hth

3 голосов
/ 02 октября 2016

Могут возникнуть проблемы при запуске процесса с multiprocessing путем вызова __init__. Вот демо:

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

3 голосов
/ 27 декабря 2009

Вы как-то reload(decimal), или monkeypatch десятичный модуль, чтобы изменить десятичный класс? Вот две вещи, которые могут вызвать такую ​​проблему.

...