简体   繁体   English

使用 C 绑定导入代码的 Pickle 模块

[英]Pickle module that imports code with C bindings

I have a class I want to pickle using this function:我有一个我想用这个函数腌制的课程:

def _pickle(self):
    """Pickle model instance.
    """
    fpath = f'{directory}/model.pickle'
    with open(fpath, 'wb') as f:
        pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)

However, in my file I import a library, PyPolyaGamma .但是,在我的文件中,我导入了一个库PyPolyaGamma It's a Python wrapper for some C code that does fast sampling from the Polya-gamma distribution.它是一些 C 代码的 Python 包装器,可以从 Polya-gamma 分布中快速采样。 When I try to pickle my class, I get this error:当我尝试腌制我的课程时,出现此错误:

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__

My understanding is that Python does not know how to serialize the PyPolyaGamma code, probably because of the dependency on C. What is the correct way to handle this?我的理解是 Python 不知道如何序列化 PyPolyaGamma 代码,可能是因为对 C 的依赖。处理这个问题的正确方法是什么?


Here is a minimal and complete example, if you're willing to install PyPolyaGamma:这是一个最小且完整的示例,如果您愿意安装 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)

This will output:这将输出:

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__

Unfortunately it looks like that pypolyagamma library you use doesn't currently support pickling/unpickling those objects, so in a word: you can't pickle them without modifying the library.不幸的是,您使用的 pypolyagamma 库目前似乎不支持酸洗/取消酸洗这些对象,所以总而言之:您不能在不修改库的情况下对它们进行酸洗。

Furthermore, since it wraps a C++ class, the pickler/unpickler isn't trivial;此外,由于它包装了一个 C++ 类,pickler/unpickler 不是微不足道的; it'd need to know what state from that wrapped class is necessary for the object to be in the same state after unpickling.它需要知道该包装类的什么状态对于解压后对象处于相同状态是必要的。

As an alternative to a wrapper and if you don't mind using a functional interface, then I would recommend using polyagamma instead.作为包装器的替代品,如果您不介意使用功能接口,那么我建议使用polyagamma代替。 This resolves issues with pickling.这解决了酸洗问题。 Its a python package for Polya-Gamma variable sampling written in C. It is flexible and allows using different sampling methods and has an API that resembles Numpy's.它是一个用 C 编写的用于 Polya-Gamma 变量采样的 python 包。它很灵活,允许使用不同的采样方法,并有一个类似于 Numpy 的 API。 You can install the latest version via pip install -U polyagamma .您可以通过pip install -U polyagamma安装最新版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM