使用 C 绑定导入代码的 Pickle 模块
Pickle module that imports code with C bindings
我有一个 class 我想用这个函数腌制:
def _pickle(self):
"""Pickle model instance.
"""
fpath = f'{directory}/model.pickle'
with open(fpath, 'wb') as f:
pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)
但是,在我的文件中我导入了一个库,PyPolyaGamma。它是一些 C 代码的 Python 包装器,可以从 Polya-gamma 分布中进行快速采样。当我尝试腌制 class 时,出现此错误:
Traceback (most recent call last):
File "fit_model.py", line 262, in <module>
model.fit(Y)
File "/Users/gwg/projects/cdnlvm/kl_gplvmbase.py", line 97, in fit
self._plot_and_print(t)
File "/Users/gwg/projects/cdnlvm/kl_nbgplvm.py", line 456, in _plot_and_print
self._pickle()
File "/Users/gwg/projects/cdnlvm/kl_gplvmbase.py", line 352, in _pickle
pickle.dump(self_, f, pickle.HIGHEST_PROTOCOL)
File "stringsource", line 2, in pypolyagamma.pypolyagamma.PyPolyaGamma.__reduce_cython__
TypeError: no default __reduce__ due to non-trivial __cinit__
我的理解是Python不知道如何序列化PyPolyaGamma代码,可能是因为对C的依赖。正确的处理方法是什么?
如果您愿意安装 PyPolyaGamma,这是一个最小的完整示例:
# pickle_test.py
import pickle
from pypolyagamma import PyPolyaGamma
class Model:
def __init__(self):
self.pg = PyPolyaGamma()
model = Model()
with open('test.pickle', 'wb+') as f:
pickle.dump(model, f)
这将输出:
Traceback (most recent call last):
File "pickle_test.py", line 15, in <module>
pickle.dump(model, f)
File "stringsource", line 2, in pypolyagamma.pypolyagamma.PyPolyaGamma.__reduce_cython__
TypeError: no default __reduce__ due to non-trivial __cinit__
不幸的是,您使用的 pypolyagamma 库目前似乎不支持 pickling/unpickling 这些对象,所以一句话:如果不修改库就无法腌制它们。
此外,由于它包装了 C++ class,因此 pickler/unpickler 并非微不足道;它需要知道 that wrapped class 中的什么状态对于对象在 unpickling 后处于相同状态是必要的。
作为包装器的替代方案,如果您不介意使用功能接口,那么我建议您改用 polyagamma。这解决了酸洗问题。它是一个用 C 编写的用于 Polya-Gamma 变量采样的 python 包。它很灵活,允许使用不同的采样方法,并且有一个类似于 Numpy 的 API。您可以通过 pip install -U polyagamma
.
安装最新版本
我有一个 class 我想用这个函数腌制:
def _pickle(self):
"""Pickle model instance.
"""
fpath = f'{directory}/model.pickle'
with open(fpath, 'wb') as f:
pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)
但是,在我的文件中我导入了一个库,PyPolyaGamma。它是一些 C 代码的 Python 包装器,可以从 Polya-gamma 分布中进行快速采样。当我尝试腌制 class 时,出现此错误:
Traceback (most recent call last):
File "fit_model.py", line 262, in <module>
model.fit(Y)
File "/Users/gwg/projects/cdnlvm/kl_gplvmbase.py", line 97, in fit
self._plot_and_print(t)
File "/Users/gwg/projects/cdnlvm/kl_nbgplvm.py", line 456, in _plot_and_print
self._pickle()
File "/Users/gwg/projects/cdnlvm/kl_gplvmbase.py", line 352, in _pickle
pickle.dump(self_, f, pickle.HIGHEST_PROTOCOL)
File "stringsource", line 2, in pypolyagamma.pypolyagamma.PyPolyaGamma.__reduce_cython__
TypeError: no default __reduce__ due to non-trivial __cinit__
我的理解是Python不知道如何序列化PyPolyaGamma代码,可能是因为对C的依赖。正确的处理方法是什么?
如果您愿意安装 PyPolyaGamma,这是一个最小的完整示例:
# pickle_test.py
import pickle
from pypolyagamma import PyPolyaGamma
class Model:
def __init__(self):
self.pg = PyPolyaGamma()
model = Model()
with open('test.pickle', 'wb+') as f:
pickle.dump(model, f)
这将输出:
Traceback (most recent call last):
File "pickle_test.py", line 15, in <module>
pickle.dump(model, f)
File "stringsource", line 2, in pypolyagamma.pypolyagamma.PyPolyaGamma.__reduce_cython__
TypeError: no default __reduce__ due to non-trivial __cinit__
不幸的是,您使用的 pypolyagamma 库目前似乎不支持 pickling/unpickling 这些对象,所以一句话:如果不修改库就无法腌制它们。
此外,由于它包装了 C++ class,因此 pickler/unpickler 并非微不足道;它需要知道 that wrapped class 中的什么状态对于对象在 unpickling 后处于相同状态是必要的。
作为包装器的替代方案,如果您不介意使用功能接口,那么我建议您改用 polyagamma。这解决了酸洗问题。它是一个用 C 编写的用于 Polya-Gamma 变量采样的 python 包。它很灵活,允许使用不同的采样方法,并且有一个类似于 Numpy 的 API。您可以通过 pip install -U polyagamma
.