【发布时间】:2013-08-29 06:11:05
【问题描述】:
我在挑选 Cython 类时遇到问题,但前提是它是在包中定义的。这个问题被注意到previously online,但他们没有说明它是如何解决的。这里有两个组件:使用__reduce__ 方法的 Cython 酸洗和包错误。
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
pickle.py 中有一个错误都变成了 PicklingError 在查看该代码后,发生的具体错误是:
ImportError: No module named reduce
健全性测试
为了检查没有某种范围或其他问题,如果我运行 pickle 模块应该执行的步骤,一切正常:
f = bar.Foo(4)
call, args = f.__reduce__()
print call(*args)
那么这里发生了什么?!
【问题讨论】:
-
查看类似问题stackoverflow.com/a/16405319/204882的答案。基本上,您不能只是移动已编译的扩展。包名必须在构建时指定。
-
嗯,成功了。我想并没有真正理解 setup.py 中的 Extension 对象是如何工作的。我会更新答案。