我该如何在Cython中使用`round()`函数?
----------更新-------------------------
在这里找到了一些线索 这里。
缺点是,官方的64位Python版本没有包含libmsvcr90.a这个文件,而我们需要它来链接正确的C运行时DLL。
-----------原帖-------------------
我的Python版本:
Python 3.3.5,使用的是Windows下的MSC v.1600 64位版本。安装并使用了Windows SDK v7.1。我已经使用Cython工作了一周,似乎其他代码运行得很好。
在这个链接中提到,round()
是一个内置函数。然而,当我在Cython代码中调用它,并使用cython my_code.pyx -a
来检查时,这个函数显示为纯黄色,意味着使用的是Python的方法。
然后我在网上查了一下,使用了:
from libc.math cimport round
但是在编译时出现了“未解决的外部符号”的错误。
我该怎么办?
这是我的代码:
from libc.math cimport round
cdef float a = 1.5
cdef float b
b = round(a)
print(b)
然后它显示:致命错误 LNK1120:1个未解决的外部错误
我的setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy as np
extensions = [
Extension('test', ['test.pyx'], include_dirs = [np.get_include()]),
]
setup(
ext_modules = cythonize(extensions)
)
我知道np.get_include()在这种情况下其实不是必须的,但我加上它是因为我经常使用numpy,这样做也没什么坏处。
我编译的命令是:
python setup.py build_ext --inplace
结果(我实际上在我的机器上使用的是setup1.py):
X:\WorkFolder\DataAnalysis\lw9pg\mol>python setup1.py build_ext --inplace
正在运行 build_ext
构建 'test' 扩展
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -IX:\WinPython3\python-3.3.5.amd64\include -IX:\WinPython3\python-3.3.5.amd64\include /Tctest.c /Fobuild\temp.win-amd64-3.3\Release\test.obj
test.c
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:X:\WinPython3\python-3.3.5.amd64\libs LIBPATH:X:\WinPython3\python-3.3.5.amd64\PCbuild\amd64 /EXPORT:PyInit_test build\temp.win-amd64-3.3\Release\test.obj /OUT:X:\WorkFolder\DataAnalysis\lw9pg\mol\test.pyd /IMPLIB:build\temp.win-amd64-3.3\Release\
test.lib /MANIFESTFILE:build\temp.win-amd64-3.3\Release\test.pyd.manifest
test.obj : 警告 LNK4197: 导出 'PyInit_test' 被多次指定;使用第一次的定义
创建库 build\temp.win-amd64-3.3\Release\test.lib 和对象 build\temp.win-amd64-3.3\Release\test.exp
test.obj : 错误 LNK2019: 在函数 __pyx_pf_4test_rounding 中引用的未解决外部符号 round
X:\WorkFolder\DataAnalysis\lw9pg\mol\test.pyd : 致命错误 LNK1120: 1个未解决的外部错误
错误:命令 '"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\link.exe"' 失败,退出状态112
0
1 个回答
如果你想测试简单的cython代码,最简单的方法就是使用 pyximport
:
假设你的代码文件叫 tester.pyx
,你可以这样运行它:
在同一个文件夹里,在一个python文件的顶部加上这段代码,然后直接运行这个文件,你会看到 print b
输出 2.0
。
import pyximport
pyximport.install()
要编译并运行一个cython函数,我使用以下的setup.py脚本:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext= Extension("tester", sources=["tester.pyx"])
setup(ext_modules=[ext],cmdclass={'build_ext': build_ext})
用下面的命令在你的 .pyx
文件上运行它, --inplace
参数会把它编译到同一个目录下:
python setup.py build_ext --inplace --compiler=mingw32 # --compiler=mingw32 only needed on windows
你会得到一个 tester.pyd
文件(在mac和linux上是tester.so),你可以像从python模块中导入函数一样导入你的函数。
这是一个简单的函数,用来对一个数字进行四舍五入:
from libc.math cimport round
def rounding(float n):
return round(n)
我可以 compile
它,或者使用 pyxinstall
导入并运行它,像这样:
In [29]: from tester1 import *
In [30]: rounding(12.3453455)
Out[30]: 12.0
使用pyximport:
In [21]: import pyximport
In [22]: pyximport.install()
Out[22]: (None, None)
from tester import *
In [23]: rounding(10.23232)
Out[23]: 10.0
我还创建了一个纯python的四舍五入方法来做对比:
def py_rounding(n):
return round(n)
import timeit
if __name__=='__main__':
print timeit.timeit('py_rounding(10.23232)','from cyt import py_rounding')
print timeit.timeit('rounding(10.23232)','from tester import rounding')
0.183354854584
0.037761926651
这个 cython
代码的速度明显更快。
这些都是非常基础的例子,你可以在 这里 找到更好的cython用法,包括在ipython中使用 %load_ext cythonmagic
。