我在腌制 Cython 类时遇到了麻烦,但只有在它是在包中定义的时候。这个问题之前在网上已经注意到了,但他们没有说明它是如何解决的。这里有两个组件:使用__reduce__
方法和包错误的 Cython 酸洗。
Cython 酸洗成功
我将首先展示它是如何在没有包部分的情况下工作的。这个例子工作正常。
赛通文件
我的 Cython 文件是reudce.pyx
:
cdef class Foo(object):
cdef int n
def __init__(self, n):
self.n = n
def __reduce__(self):
return Foo, (self.n,)
设置文件
这可以编译为setup.py
:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("reduce", ["reduce.pyx"])]
)
通过执行python setup.py build && cp build/lib*/reduce.so .
测试脚本
测试脚本被调用test_reduce.py
并且是:
import reduce
import pickle
f = reduce.Foo(4)
print pickle.dumps(f)
执行python test_reduce.py
工作正常。
包装失败中的 Cython 酸洗
但是,一旦将reduce.pyx
其放入包中,就会出现错误。
包创建
要重现这一点,首先创建一个名为bar
.
mkdir bar
mv reduce.so bar
echo "from reduce import Foo" > bar/__init__.py
测试脚本
将文件更改test_reduce.py
为:
import bar
import pickle
f = bar.Foo(4)
print pickle.dumps(f)
错误信息
运行python test_reduce.py
给出以下错误:
File "/usr/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 748, in save_global
(obj, module, name))
pickle.PicklingError: Can't pickle <type 'reduce.Foo'>: it's not found as reduce.Foo
在查看该代码后,有一个错误都变成了 PicklingError ,pickle.py
发生的具体错误是:
ImportError: No module named reduce
理智测试
要检查是否存在某种范围或其他问题,如果我运行 pickle 模块应执行的步骤,一切正常:
f = bar.Foo(4)
call, args = f.__reduce__()
print call(*args)
那么这里发生了什么?!