Ошибка Pickle при сериализации класса Cython с помощью лямбды - PullRequest
2 голосов
/ 10 апреля 2020

Я использую маринад и укроп для следования лямбда-функции и отлично работает:

import dill
import pickle

f = lambda x,y: x+y
s = pickle.dumps(f)

или даже при использовании в классе, например:

file

foo.py

class Foo(object):
    def __init__(self):
        self.f = lambda x, y: x+y 

file

test.py

import dill
import pickle
from foo import Foo

f = Foo()
s = pickle.dumps(f)  # or  s = dill.dumps(f)

но при сборке одного и того же файла в формате .pyx (foo.pyx) с использованием cython, невозможно сериализовать с помощью укропа, маринада или cpickle, появляется эта ошибка:

Трассировка (последний вызов был последним): файл "/home/amin/anaconda2/envs/rllab2/lib/python2.7/site-packages/IPython/core/interactiveshell.py", строка 2878, в run_cod exe c (code_obj, self.user_global_ns, self.user_ns) Файл "", строка 1, в файле a = pickle.dumps (c) "/home/amin/anaconda2/envs/rllab2/lib/python2.7 /pickle.py ", строка 1380, в дампах Pickler (файл, протокол) .dump (obj) Файл" /home/amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py ", строка 224 , в дампе self.save (obj) Файл "/home/amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py", строка 331, в сохраненных файлах Файл elf.save_reduce (obj = obj, * rv) "/home/amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py", строка 425, в файле сохранения (состояния) save_reduce "/ home /amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py ", строка 286, в save f (self, obj) # Вызов несвязанного метода с явным файлом self" / home / amin / anaconda2 / envs /rllab2/lib/python2.7/site-packages/dill/_dill.py ", строка 912, в файле save_module_dict StockPickler.save_dict (pickler, obj) Файл" / home / amin / anaconda2 / envs / rllab2 / lib / python2 .7 / pickle.py ", строка 655, в файле save_dict self._batch_setitems (obj.iteritems ()) Файл" /home/amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py ", строка 669, в _batch_setitems save (v) File" /home/amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py ", строка 317, в save self.save_global (obj, rv) Файл "/home/amin/anaconda2/envs/rllab2/lib/python2.7/pickle.py", строка 754, в save_global (obj, module, name)) PicklingError: Невозможно засолить. в 0x7f9ab1ff07d0>: он не найден как foo.lambda

файл setup.py для сборки cython

setup.py

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize("foo.pyx"))

затем запустите в терминале:

python setup.py build_ext --inplace

Есть ли способ

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Я dill автор. Более подробно о том, что @DavidW говорит в комментариях, - я полагаю, что (в настоящее время) нет известных сериализаторов, которые могут перебирать лямбда-символы cython или подавляющее большинство кода на cython. Действительно, сериализаторам python гораздо сложнее выбирать объекты с расширениями C, если авторы кода расширения C специально не создают инструкции сериализации (как это делали numpy и pandas). , В этом ключе ... вместо лямбды можно создать класс с помощью метода __call__, чтобы он действовал как функция ..., а затем добавить один или несколько методов pickle (__reduce__, __getstate__). , __setstate__ или что-то подобное) ... и тогда вы сможете выбирать экземпляры своего класса. Это немного трудоемко, но так как этот путь использовался для выбора классов, написанных на C ++ - я думаю, вы должны заставить его работать для классов, построенных на Cython.

0 голосов
/ 10 апреля 2020

В этом коде импорт укропа импорта укропа

f = лямбда х, у: x + ys = pickle.dumps (f) f - это функция, но в другом коде импорта укропа импорт маринада из foo import Foo

f = Foo () s = pickle.dumps (f) # или s = dill.dumps (f) f является классом

...