我在选择Cython类时遇到麻烦,但仅限于在包中定义它时。该问题先前已在网上指出,但他们没有说明如何解决。这里有两个组成部分:使用__reduce__
方法的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
工作正常。
但是,一旦将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
pickle.py
在查看该代码之后,所有错误都变成了PicklingError ,正在发生的特定错误是:
ImportError: No module named reduce
要检查是否没有某种范围或其他问题,如果我运行pickle模块应执行的步骤,则一切正常:
f = bar.Foo(4)
call, args = f.__reduce__()
print call(*args)
那这是怎么回事?!
问题出在构建脚本中。该Pickle
模块使用__module__
函数/类的属性进行酸洗。该__module__
属性来自脚本中Extension()
构造函数的第一个参数setup.py
。由于我将构造函数定义为Extension('reduce', ['reduce.pyx'])
,因此__module__
属性为reduce
。应该是bar/reduce
因为它现在在包装中。
使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('bar/reduce', ['reduce.pyx'])]
)
解决了问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句