通过 pickle 保存 cython 扩展

mj *_*eri 4 python pickle cython python-3.x cythonize

我有一个类或扩展类型,cython如下所示:

cdef class Self_Organized_Map:
     cdef 
     def __cinit__(self,np.ndarray data,.....):
     ....
Run Code Online (Sandbox Code Playgroud)

我使用此cython文件(其名称为som.pyx)创建了一个 python 模块distutils,然后将其导入python并用它来创建和训练模型,但是当我想使用它保存模型时,pickle它给了我这个错误:

TypeError:无法腌制 som.Self_Organized_Map 对象

pickle 或我的代码有什么问题?pickle 无法保存扩展对象吗?

Dav*_*idW 5

Cython 类默认情况下不可 pickle,因此您需要自己实现Pickle 接口。您可以在许多不同的级别上执行此操作,但 和__getstate____setstate__最用户友好的级别,因此这是一个很好的起点,除非您有充分的理由。

如果类的内容是可腌制的,那么就像在 中返回它们的元组__getstate__并在 中执行相反操作一样简单__setstate__。内存视图本身是不可pickle的,但有一个base属性可以。

cdef class C:
    cdef double[:] array
    cdef python_obj
    cdef int integer

    def __init__(self,array,python_obj,integer):
        self.array = array
        self.python_obj = python_obj
        self.integer = integer

    def __getstate__(self):
        return (self.array.base, # memoryviews aren't pickleable, need to get underlying object
                          # and hope it's pickleable
                self.python_obj, self.integer)

    def __setstate__(self,x):
        self.array, self.python_obj, self.integer = x
Run Code Online (Sandbox Code Playgroud)

如果您的类包含 C 或 C++ 对象,那么情况会复杂得多。对于简单类型,最好的起点是将内存复制到字节数组中或利用 Cython 的默认struct<->dict相互转换。但是,如果类包含指针,那么这将不起作用,您需要在 C/C++ 中为其实现可靠的加载/保存机制。