在pickle一个类时,我在cython中的python中得到了不同的行为

时间:2012-10-17 19:28:56

标签: python import pickle cython

我有以下文件层次结构:

python/apps/A.py
      /geometrylib/__init__.py
      /geometrylib/B.py
      /geometrylib/geometry.py
      /geometrylib/goemetry.pyx
      /geometrylib/goemetry.pyd

geometry.pyx和geometry.py包含相同的类Camera(cython版本使用cdef定义类)。 A.py和B.py都导入几何模块。

如果我导入cython版本(编译为geometry.pyd),我可以正确地从python / geometrylib文件夹中的B.py中拾取Camera。但是我不能在python / apps文件夹中从A.py中腌制Camera,我得到以下异常:

pickle.PicklingError:不能发痒:找不到它几何。相机

但是,如果我删除geometry.pyd而我导入python版本(geometry.py),那么我可以从A.py或B.py中腌制相机。除了删除geometry.pyd,同样的python命令行,在两种情况下从同一文件夹运行都没有别的变化。 为什么会出现这种差异?

挖掘一下我发现异常发生在C:\ Python27 \ Lib \ pickle.py第742行

try:
    __import__(module)            #line 742
    mod = sys.modules[module]
    klass = getattr(mod, name)
except (ImportError, KeyError, AttributeError):
    raise PicklingError(
        "Can't pickle %r: it's not found as %s.%s" %
        (obj, module, name))

在A.py中我导入cython版本(geometry.pyd),(我挑选一个Camera实例来触发预测)模块是“几何”,__import__(module)触发异常。在A.py中我导入python版本(geometry.py),(我挑选一个Camera实例来触发预期)模块是“geometrylib.geometry”,__import__(module)正确导入模块。

我已经通过将python / geometrylib添加到PYTHONPATH解决了这个问题,然后我可以使用cython版本正确地从A.py和B.py中选择Camera。

这是怎么回事?我不喜欢我的解决方案。 有没有人有更好的解决方案?

已编辑以添加一些额外信息。

另外,根据请求,这是我用来构建cython扩展的setup.py。

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy

setup(
    cmdclass = { 'build_ext': build_ext},
    ext_modules = [Extension("geometry", ['geometry.pyx'], include_dirs=[numpy.get_include(), "."])])

1 个答案:

答案 0 :(得分:4)

您正在将geometry.pyx构建为顶级模块,而实际上它是geometrylib包的一部分。因此,Camera类被分配了错误的__module__值(geometry而不是geometrylib.geometry),并且当pickler尝试查找名为{{1}的顶级模块时,它会失败}。

您应遵循标准打包指南,即将setup.py放入顶级模块(geometrylib)旁边的“Python”文件夹中。安装调用将如下所示:

geometry