比如说我有一个剧本 fib.py
. 里面有一些doctests。
def fib(n):
"""Return the nth number in the Fibonacci sequence.
>>> fib(0)
0.0
>>> fib(1)
1.0
>>> fib(4)
3.0
>>> fib(7)
13.0
"""
a, b = 0.0, 1.0
for i in range(n):
a, b = a + b, a
return a
if __name__ == "__main__":
import doctest
doctest.testmod()
所有的工作都和预期的一样,我可以通过检查输出的 python3 fib.py -v
.
好了,现在我要把它翻译成Cython,为了方便起见,我甚至要去掉这个 if __name__ == '__main__'
条件性.让我们把我们的Cython文件称为 fib.pyx
#cython: language_level=3
def fib(int n):
"""Return the nth number in the Fibonacci sequence.
>>> fib(0)
0.0
>>> fib(1)
1.0
>>> fib(4)
3.0
>>> fib(7)
13.0
"""
cdef int i
cdef double a=0.0, b=1.0
for i in range(n):
a, b = a + b, a
return a
import doctest
doctest.testmod()
当然,我们需要编译我们的Cython。对我来说,那就是
cython --embed fib.pyx
gcc $(python-config --cflags) $(python-config --ldflags) fib.c
这就产生了 a.out
.
如果我尝试 ./a.out -v
我得到...
1 items had no tests:
__main__
0 tests in 1 items.
0 passed and 0 failed.
Test passed.
我的测试怎么了?
好吧,这里有几个问题. . .
首先我没有真正正确编译。最后的结果应该是 .so
MacOsLinux系统上的文件和一个 .pyd
文件。
你可以通过写一个 setup.py
档案
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('fib.pyx'))
根据你的操作系统和python版本,运行
python setup.py build_ext --inplace
会产生类似 fib.cpython-37m-x86_64-linux-gnu.so
更多信息请参见相关 骏马文档.
pip install pytest
pip install pytest-cython
在编译后的Cython所在的目录下运行 。
pytest --doctest-cython -v
在编译后的目录下,运行 -v
当然是 verbose
并提供额外的输出。
从 pytest --help | grep cython
我们可以看看这个命令在做什么。
cython:
--doctest-cython run doctests in all .so and .pyd modules
--cython-ignore-import-errors