如何将 Cython 与 pytest 一起使用?
How to use Cython with pytest?
目标是为使用 Cython 的 Python3 项目使用 pytest
单元测试框架。这不是即插即用的东西,因为 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'
另一个不成功的解决方案我得到是使用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'
它似乎无法识别该模块。也许这是由于某些 absolute/relative import mojo 我不明白。
如何将 pytest
与 Cython 一起使用?我如何才能发现这些方法不起作用的原因并加以修复?
最终更新:
在考虑了原始问题和问题更新后(感谢@hoefling 解决了这些问题!),现在这个问题被简化为:
why can pytest no import the Cython module calculateScore, even though running the code just with python (no pytest) works just fine?
正如@hoefling 所建议的,应该使用 pytest-runner
版本 <0.4 来避免
AttributeError: type object 'test' has no attribute 'install_dists'
然后回答实际的和最后的问题(除了部分,off-topic,user-specific 修复添加到问题 post 本身)为什么 pytest
不能导入 Cython 模块 calculateScore
,即使 运行 使用 python 的代码(没有 pytest)工作得很好:
剩下的问题已经解决 here.
目标是为使用 Cython 的 Python3 项目使用 pytest
单元测试框架。这不是即插即用的东西,因为 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'
另一个不成功的解决方案我得到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'
它似乎无法识别该模块。也许这是由于某些 absolute/relative import mojo 我不明白。
如何将 pytest
与 Cython 一起使用?我如何才能发现这些方法不起作用的原因并加以修复?
最终更新: 在考虑了原始问题和问题更新后(感谢@hoefling 解决了这些问题!),现在这个问题被简化为:
why can pytest no import the Cython module calculateScore, even though running the code just with python (no pytest) works just fine?
正如@hoefling 所建议的,应该使用 pytest-runner
版本 <0.4 来避免
AttributeError: type object 'test' has no attribute 'install_dists'
然后回答实际的和最后的问题(除了部分,off-topic,user-specific 修复添加到问题 post 本身)为什么 pytest
不能导入 Cython 模块 calculateScore
,即使 运行 使用 python 的代码(没有 pytest)工作得很好:
剩下的问题已经解决 here.