腌制一个类时,我在 python 中的行为与在 cython 中的行为不同
Posted
技术标签:
【中文标题】腌制一个类时,我在 python 中的行为与在 cython 中的行为不同【英文标题】:When pickling a class I get different behavior in python that in cython 【发布时间】:2012-10-08 03:48:13 【问题描述】:我有以下文件层次结构:
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 中正确腌制相机。但是我无法从 python/apps 文件夹中的 A.py 中提取相机,我得到以下异常:
pickle.PicklingError: Can't pickle : it's not found as geometry.Camera
但是,如果我删除geometry.pyd 并改为导入python 版本(geometry.py),那么我可以从A.py 或B.py 中腌制Camera。除了删除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)时,(我腌制一个相机实例来触发期望)模块是“几何”并且__import__(module)
触发异常。在 A.py 中,我导入了 python 版本(geometry.py),(并且我腌制了一个相机实例来触发期望)模块是“geometrylib.geometry”,__import__(module)
正确导入了模块。
我已经通过将 python/geometrylib 添加到 PYTHONPATH 解决了这个问题,然后我可以使用 cython 版本正确地从 A.py 和 B.py 中提取相机。
这应该如何工作?我不喜欢我的解决方案。 有人有更好的解决方案吗?
已编辑以添加一些额外信息。
另外,根据要求,这是我用来构建 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(), "."])])
【问题讨论】:
执行 Cython 版本与纯 Python 版本时,Python 命令行是什么样的?在哪个目录下执行 Python 命令? [不小心按回车没有完成] 你是如何编译 Cython 模块的?请记住:Cython 文件通常编译到不同的目录中,因此您需要告诉它在哪里可以找到要导入的其余模块。也许您可以作为setup.py
的一部分来执行此操作,但老实说,如果没有任何其他信息,我无法告诉您。
感谢您的评论,请参阅我上面的编辑
【参考方案1】:
您将geometry.pyx 构建为***模块,而实际上它是geometrylib
包的一部分。结果,Camera
类被分配了不正确的__module__
值(geometry
而不是geometrylib.geometry
),并且pickler 在尝试查找名为geometry
的***模块时失败。
您应该遵循标准打包指南,即将 setup.py 放入***模块 (geometrylib) 旁边的“Python”文件夹中。设置调用将如下所示:
setup(
cmdclass = 'build_ext': build_ext,
ext_modules = [Extension("geometrylib.geometry", ['geometrylib/geometry.pyx'], include_dirs=[numpy.get_include(), "."])])
【讨论】:
这样就解决了问题!我不知道这是标准包装指南,我会阅读它们!以上是关于腌制一个类时,我在 python 中的行为与在 cython 中的行为不同的主要内容,如果未能解决你的问题,请参考以下文章
UImenucontroller 在 App Store 中的行为与在开发中的行为不同
我在 python3 中使用协议 3 腌制了文件,现在我需要用 python2 解压缩它们,我该怎么办?
我在 python3 中使用协议 3 腌制了文件,现在我需要用 python2 解压缩它们,我该怎么办?