如何准备cython子模块

时间:2017-05-18 09:19:39

标签: cython

我有三个问题,但有关系,我没有得到如何将它们分开。我发现了很多关于这些问题的信息,例如submodule extensionhierarchy,关于empty __init__.py file以及如何cythonize multiple pyx files。但是当我一起尝试时,我无法让它们发挥作用。

我已经准备好small repo一起思考问题的代码示例。我甚至检查了一些使用cython的projects listed的代码,但仍然没有得到如何同时做三件事。

  • 清空 __ init __。py 文件:

在一个项目中(所有文件都是 pyx (以及 pxd ifneedbe)),带有 __ init __。pyx ,其中包括所有文件它们,当有一个 __ init __。py 文件,然后导入它不会加载“ .so ”但是空的init。

  • cythonize多个文件:

而不是准备包含模块所有元素的 __ init __。py 。像:

cythonize(['factory.pyx', 'version.pyx'])

生成的“ .so ”导入引发异常:

>>> import barfoo
(...)
ImportError: dynamic module does not define init function (PyInit_barfoo)

如果有必要在 __ init __。py 中写一些东西,那么它与上一个问题有关。

  • 子模块:

事实上,这是主要问题。 singleton.pyx 是子模块的一部分,假设 utils 可以从模块中的其他元素中使用。

对于示例,在 setup.py 中添加了一个子模块(简称为 subm )作为另一个扩展。我放置的时间早于主要的(我不知道这是否确实有任何区别,我没有看到它)。

>>> import barfoo
>>> import barfoo.subm
(...)
ImportError: No module named 'barfoo.subm'

另外,这些食谱有效,但我不能。当“ py ”和“ pyx ”文件混合使用时,“ __ init __。py ”似乎是必要的。这些示例解释了如何使用多个文件进行cython化,但不包括导入的最后一个关键点。并且子模块没有完成如何从一个地方或另一个地方导入它们(导入子模块时导入子模块,或者指定它们时可选导入)。

2 个答案:

答案 0 :(得分:2)

昨晚我看到了你的问题,根据wiki做了一个简单的例子。但这个问题很快被删除了。

以下是示例:https://github.com/justou/cython_package_demo

确保C编译器和python环境的设置正确,通过运行编译pyx文件:

python setup.py build_ext --inplace

用法与python包相同:

from dvedit.filters import flip, inverse, reverse
flip.show()       # print: In flip call Core function
inverse.show()    # print: In inverse call Core function
reverse.show()    # print: In reverse call Core function

BTW,无需创建__init__.pyx,您可以在__init__.py文件中执行ext_module导入

答案 1 :(得分:2)

感谢oz1DavidW的评论,我得到了solution。是的,这三件事情汇集在一起​​。

  • 非常重要是在 setup.py 中导入时的顺序。即使PEP8没有说输入应该按字母顺序排序,还有其他指导方针(例如reddit' s),我通常遵循这些指南:

首先导入 cythonize 然后 setup ,当调用 cythonize(find_pyx())时,结果将是 distutils.extension.Extension 对象的列表。

from setuptools import setup, find_packages
from Cython.Build import cythonize
必须在 cython 之前导入

setuptools ,然后 cythionize()的结果将是 setuptools.extension的列表。可以传递给 setup()调用的扩展对象。

  • 重要了解 __ init __ 的含义:

所有带有includes的 __ init __。pyx 文件已被删除,每个 .pxy 文件都会生成自己的 .so 二进制文件。

主模块和子模块将存在,只要它们的目录包含 __ init __。py 文件,就像纯python代码一样。

在我已链接的示例中,文件 barfoo / __ init __。py 不为空,因为我希望 import barfoo 提供对 version()或 Factory()。然后,这个 __ init __。py 就像普通的纯Python那样导入它们。

  • 对于子模块:

类似于子模块及其自己的 __ init __。py 文件。在此示例中, import barfoo 将从.factory导入工厂执行,他将从barfoo.subm导入栏调用,然后 > subm 将可用。

但如果子模块未以此辅助方式导入,则用户可以通过 import barfoo.subm 等调用访问它。