通过 pickle 保存 cython 扩展
save cython extension by pickle
我有一个 class 或用 cython
编写的扩展类型,如下所示:
cdef class Self_Organized_Map:
cdef
def __cinit__(self,np.ndarray data,.....):
....
我使用 distutils
从这个 cython
文件(它的名字是 som.pyx
)创建了一个 python 模块,然后我将它导入 python
并用它来创建和训练模型,但是当我想使用 pickle
保存我的模型时,它给了我这个错误:
TypeError: can't pickle som.Self_Organized_Map objects
泡菜或我的代码有什么问题? pickle 不能保存扩展对象吗?
Cython classes 默认情况下不可 pickleable,因此您需要自己实现 Pickle interface。您可以在许多不同的级别上执行此操作,但 __getstate__
和 __setstate__
是最用户友好的级别,因此除非您有充分的理由,否则它是一个很好的起点。
如果 class 的内容是可腌制的,就像在 __getstate__
中返回它们的元组和在 __setstate__
中进行反向操作一样简单。 Memoryviews 本身不可 pickleable,但有一个 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
如果您的 class 持有 C 或 C++ 对象,那么它会复杂得多。对于简单类型,开始的好地方只是将内存复制到字节数组或利用 Cython 的默认 struct<->dict
相互转换。但是,如果 class 包含指针,那么这将不起作用,您需要在 C/C++ 中为其实现可靠的 load/save 机制。
自 Cython 0.26(2017 年 7 月发布)以来,cdef 类 可以自动 pickle,只要它们不包含指针或联合。对于 类 包含的结构,可以使用 @cython.auto_pickle(True)
装饰器启用自动酸洗。由于高代码开销和其他原因,默认情况下禁用它。
可以在 changelog and on the website of Stefan Behnel 中找到更多信息。
我有一个 class 或用 cython
编写的扩展类型,如下所示:
cdef class Self_Organized_Map:
cdef
def __cinit__(self,np.ndarray data,.....):
....
我使用 distutils
从这个 cython
文件(它的名字是 som.pyx
)创建了一个 python 模块,然后我将它导入 python
并用它来创建和训练模型,但是当我想使用 pickle
保存我的模型时,它给了我这个错误:
TypeError: can't pickle som.Self_Organized_Map objects
泡菜或我的代码有什么问题? pickle 不能保存扩展对象吗?
Cython classes 默认情况下不可 pickleable,因此您需要自己实现 Pickle interface。您可以在许多不同的级别上执行此操作,但 __getstate__
和 __setstate__
是最用户友好的级别,因此除非您有充分的理由,否则它是一个很好的起点。
如果 class 的内容是可腌制的,就像在 __getstate__
中返回它们的元组和在 __setstate__
中进行反向操作一样简单。 Memoryviews 本身不可 pickleable,但有一个 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
如果您的 class 持有 C 或 C++ 对象,那么它会复杂得多。对于简单类型,开始的好地方只是将内存复制到字节数组或利用 Cython 的默认 struct<->dict
相互转换。但是,如果 class 包含指针,那么这将不起作用,您需要在 C/C++ 中为其实现可靠的 load/save 机制。
自 Cython 0.26(2017 年 7 月发布)以来,cdef 类 可以自动 pickle,只要它们不包含指针或联合。对于 类 包含的结构,可以使用 @cython.auto_pickle(True)
装饰器启用自动酸洗。由于高代码开销和其他原因,默认情况下禁用它。
可以在 changelog and on the website of Stefan Behnel 中找到更多信息。