目录
Python & C/C++
近来用Python用的越来越多,对这种十分灵活的动态语言的哲学也有了较深的理解。虽然Python有不少缺点,如没有强类型,GIL全局锁,没有编译因此效率底下,但正因为其动态性,它非常适合写软件的Prototype。因此一种典型而高效的工作流程是先用Python调用各种轮子,快速实现软件原型,然后再优化代码,将稳定的部分用C++或其他编译语言进行重写,变成一个供调用的库。
在这个过程中就难免碰到Python与C++相互调用的问题,尤其体现在:
- 在原型开发阶段,如何将现有的C++库封装成Python能够方便调用的库,避免重造轮子
- 当原型开发结束后,如何将Python代码高效地转换成其他语言的代码
能够完成Python与C/C++相互操作的方式有很多,可以参见知乎的这篇专栏,但是本文介绍的Cython却鲜有详细或通俗的中文资料。Cython是个易用的Python扩展,在Anaconda等发行包里面都自带了,可以用Python的语法写出Python的C语言扩展。因此我选择这一款扩展库学习,之后也会把相关的学习经验写下来~
安装与基本使用
后文中的环境都是在 Windows10 + Visual Studio 2017 下
Cython在流行的Python发行版本中都有被包含,包括Anaconda、Canopy、Pythonxy和Sage等。如果使用普通的Python的话可以使用pip安装:pip install Cython
。
简单运行Cython代码
从语言层面来说,Cython是一种拓展的Python,其文件的扩展名为.pyx
。这种类型的文件通过编译之后可以变成供Python直接调用的动态链接库(Linux/Mac下是.so
,Windows下是.pyd
)。根据官方文档,主要如下几编译方式:
- (推荐) 通过
setup.py
中调用Cython.Build
进行编译 - 使用
pyximport
调用.pyx
文件,这种方法.pyx
文件相当于普通的.py
文件 - 在命令行使用
cython
命令从.pyx
文件生成.c
文件,再使用外部编译器将.c
文件编译成Python可用的库 - 使用
Jupyter Notebook
或者Sage Notebook
直接运行Cython代码
这上面四种方法里最简单的是第三种方法。运行cythonize -i <.pyx File>
即可编译.pyx
成二进制库,并保存在与.pyx
文件相同的目录下。cythonize
命令有其他的参数,可以通过命令行查看。这个命令也可以通过python -m Cython.Build.Cythonize -i <.pyx File>
来完成。
不过推荐使用的是第一种方法,原理也就是通过指定distutils
或者setuptools
库中的ext_modules
参数来编译Cython代码。以官方示例为例,它的setup.py
文件如下
|
|
其中hello.pyx
的代码为
|
|
编辑保存之后直接运行python setup.py build_ext --inplace
即可进行编译。其中--inplace
参数可以让对应的链接库生成在源代码所在的目录。
编译中可能遇到的问题有
error: command 'cl.exe' failed: No such file or directory
: 这说明在环境中没有找到C编译器。由于我电脑中安装了Visual Studio,我的解决方法是根据平台使用VS的x86 Native Command Prompt或x64 Native Command Prompt来运行编译命令。此外还可以选择通过python setup.py build_ext --inplace --compiler=mingw32
使用Anaconda内置的MinGW32编译器,不过这种情况下还可能会遇到内置MinGW32的问题,具体的解决方法在链接里。
编译之后直接通过import hello
或from hello import say_hello_to
即可调用这个编译好的库。
复杂Cython工程的setup.py
如果的Cython工程中有很多.pyx
文件,甚至有很多.cpp
文件需要编译,那么这时候最好使用setup.py
进行编译,并使用Cython.Build.cythonize
模块。具体编写方式如下:
|
|
最后的setup
部分还有另一种写法:
|
|
这样的写法可以让安装整个库的时候一起执行掉Cython代码的编译和安装。此外,如果要在编译.pyx
和.cpp
时指定语言或者编译参数,在Extension
类的构造函数中添加合适的参数即可。
总结
本文介绍了Cython的安装与初步使用,看完以后就已经可以动手试试写Cython代码啦~Cython语言的特性也有不少,掌握其中的一小部分就能大大提高你的Python代码的运行效率!这些内容将会在之后的文章中讲述~
Cython的完整介绍可以参考Cython官网 Cython代码的编译还有其他方法,参见Cython文档的编译部分