目录
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文档的编译部分