如何在pytest中使用Cython?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在pytest中使用Cython?相关的知识,希望对你有一定的参考价值。

目标是将pytest单元测试框架用于使用Cython的Python3项目。这不是一个即插即用的东西,因为默认情况下pytest无法导入Cython模块。

一个不成功的解决方案是使用pytest-cython插件,但它根本不适用于我:

> py.test --doctest-cython
usage: py.test [options] [file_or_dir] [file_or_dir] [...]
py.test: error: unrecognized arguments: --doctest-cython
  inifile: None
  rootdir: /censored/path/to/my/project/dir

要验证我是否安装了软件包:

> pip freeze | grep pytest-cython
pytest-cython==0.1.0

更新:我正在使用PyCharm,它似乎没有使用我的pip安装的包,而是使用自定义(?)pycharm存储库用于我的项目使用的包。一旦我将pytest-cython添加到该存储库,该命令运行但奇怪的是它无论如何都无法识别Cython模块,尽管package / add-on是专门为此目的而设计的:

> pytest --doctest-cython
Traceback:
tests/test_prism.py:2: in <module>
    from cpc_naive.prism import readSequence, processInput
cpc_naive/prism.py:5: in <module>
    from calculateScore import calculateScore, filterSortAlphas, 
calculateAlphaMatrix_c#, incrementOverlapRanges  # cython code
E   ImportError: No module named 'calculateScore'

我得到here的另一个不成功的解决方案是使用pytest-runner,但这会产生:

> python3 setup.py pytest
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or: setup.py --help [cmd1 cmd2 ...]
   or: setup.py --help-commands
   or: setup.py cmd --help

error: invalid command 'pytest'

更新:

我首先忘了将setup_requires=['pytest-runner', ...]tests_require=['pytest', ...]添加到安装脚本中。一旦我这样做,我又得到了一个错误:

> python3 setup.py pytest
Traceback (most recent call last):
  File "setup.py", line 42, in <module>
    tests_require=['pytest']
(...)
AttributeError: type object 'test' has no attribute 'install_dists'

更新2(setup.py):

from distutils.core import setup
from distutils.extension import Extension

from setuptools import find_packages
from Cython.Build import cythonize
import numpy

try:  # try to build the .c file
    from Cython.Distutils import build_ext
except ImportError:  # if the end-user doesn't have Cython that's OK; you should have shipped the .c files anyway.
    use_cython = False
else:
    use_cython = True

cmdclass = {}
ext_modules = []

if use_cython:
    ext_modules += [
        Extension("cpc_naive.calculateScore", ["cpc_naive/calculateScore.pyx"],
                  extra_compile_args=['-g'],   # -g for debugging
                  define_macros=[('CYTHON_TRACE', '1')]),
    ]
    cmdclass.update({'build_ext': build_ext})
else:
    ext_modules += [
        Extension("cpc_naive.calculateScore", ["cpc_naive/calculateScore.c"],
                  define_macros=[('CYTHON_TRACE', '1')]),  # compiled C files are stored in /home/pdiracdelta/.pyxbld/
    ]

setup(
    name='cpc_naive',
    author=censored,
    author_email=censored,
    license=censored,
    packages=find_packages(),
    cmdclass=cmdclass,
    ext_modules=ext_modules,
    install_requires=['Cython', 'numpy'],
    include_dirs=[numpy.get_include()],
    setup_requires=['pytest-runner'],
    tests_require=['pytest']
)

更新3(部分修复):正如@hoefling所建议的那样,我将pytest-runner降级为版本<4(实际上是3.0.1),这解决了更新1中的错误,但现在我得到了与pytest-cython解决方案相同的异常:

E   ImportError: No module named 'calculateScore'

它似乎没有认出该模块。也许这是由于我不明白的一些绝对/相对导入的魔力。

如何在Cython中使用pytest?我怎样才能发现为什么这些方法不起作用然后修复它?

最终更新:在考虑原始问题和更新问题之后(感谢@hoefling解决这些问题!),这个问题现在简化为以下问题:

为什么pytest不能导入Cython模块calculateScore,即使运行代码只是用python(没有pytest)工作得很好?

答案

正如@hoefling建议的那样,应该使用pytest-runner版本<0.4来避免

AttributeError: type object 'test' has no attribute 'install_dists'

然后回答实际和最后的问题(除了部分,偏离主题,用户特定的修补程序添加到问题帖子本身)为什么pytest无法导入Cython模块calculateScore,即使运行代码只是使用python(没有pytest )工作得很好:剩下的问题解决了here

以上是关于如何在pytest中使用Cython?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IDE 中调试 Cython

如何在 cython 模块中使用外部包装类?

如何使用 pybrain 等外部 python 库在 cython 中编译我的 python 代码

如何手动编译使用 C++ 的 Cython 代码?

如何使用 cython 将 python 类公开给 c++

python pytest片段