mirror of
https://github.com/apachecn/ailearning.git
synced 2026-02-10 05:45:40 +08:00
244 lines
3.5 KiB
Markdown
244 lines
3.5 KiB
Markdown
# Cython:Cython 基础,将源代码转换成扩展模块
|
||
|
||
## Cython 基础
|
||
|
||
之前使用了手动的方法对 `C` 程序进行编译,而 `Cython` 则简化了这个过程。
|
||
|
||
考虑之前的斐波拉契数列,`Python` 版本:
|
||
|
||
```py
|
||
def fib(n):
|
||
a,b = 1,1
|
||
for i in range(n):
|
||
a,b = a+b, a
|
||
return a
|
||
|
||
```
|
||
|
||
`C` 版本:
|
||
|
||
```py
|
||
int fib(int n) {
|
||
int tmp, i, a, b;
|
||
a = b = 1;
|
||
for (i=0; i<n; i++) {
|
||
tmp = a; a += b; b = tmp;
|
||
}
|
||
return a;
|
||
}
|
||
|
||
```
|
||
|
||
`Cython` 版本:
|
||
|
||
```py
|
||
def fib(int n):
|
||
cdef int i, a, b
|
||
a,b = 1,1
|
||
for i in range(n):
|
||
a,b = a+b, a
|
||
return a
|
||
|
||
```
|
||
|
||
这里 `cdef` 定义了 `C` 变量的类型。
|
||
|
||
**Cython** 的好处在于,我们使用了 **Python** 的语法,又有 **C/C++** 的效率,同时省去了之前直接编译成扩展模块的麻烦,并且提供了原生的 **Numpy** 支持。
|
||
|
||
官方网址:[http://www.cython.org](http://www.cython.org)
|
||
|
||
其主要用法有两点:
|
||
|
||
* 将 Python 程序转化为 C 程序
|
||
* 包装 C/C++ 程序
|
||
|
||
## 将源代码转换成扩展模块
|
||
|
||
### ipython 中使用 Cython 命令
|
||
|
||
导入 `Cython` `magic` 命令:
|
||
|
||
In [1]:
|
||
|
||
```py
|
||
%load_ext Cython
|
||
|
||
```
|
||
|
||
使用 `magic` 命令执行 `Cython`:
|
||
|
||
In [2]:
|
||
|
||
```py
|
||
%%cython
|
||
def cyfib(int n):
|
||
cdef int i, a, b
|
||
a,b = 1,1
|
||
for i in range(n):
|
||
a,b = a+b, a
|
||
return a
|
||
|
||
```
|
||
|
||
In [3]:
|
||
|
||
```py
|
||
cyfib(10)
|
||
|
||
```
|
||
|
||
Out[3]:
|
||
|
||
```py
|
||
144
|
||
```
|
||
|
||
### 使用 distutils 编译 Cython
|
||
|
||
`Cython` 代码以 `.pyx` 结尾,先通过 cython 转化为 `.c` 文件,再用 `gcc` 转化为 `.so(.pyd)` 文件。
|
||
|
||
In [4]:
|
||
|
||
```py
|
||
%%file fib.pyx
|
||
def cyfib(int n):
|
||
cdef int i, a, b
|
||
a,b = 1,1
|
||
for i in range(n):
|
||
a,b = a+b, a
|
||
return a
|
||
|
||
```
|
||
|
||
```py
|
||
Writing fib.pyx
|
||
|
||
```
|
||
|
||
In [5]:
|
||
|
||
```py
|
||
%%file setup.py
|
||
from distutils.core import setup
|
||
from distutils.extension import Extension
|
||
from Cython.Distutils import build_ext
|
||
|
||
ext = Extension("fib", sources=["fib.pyx"])
|
||
|
||
setup(ext_modules=[ext], cmdclass={'build_ext': build_ext})
|
||
|
||
```
|
||
|
||
```py
|
||
Overwriting setup.py
|
||
|
||
```
|
||
|
||
编译成功:
|
||
|
||
In [6]:
|
||
|
||
```py
|
||
!python setup.py build_ext --inplace
|
||
|
||
```
|
||
|
||
```py
|
||
running build_ext
|
||
cythoning fib.pyx to fib.c
|
||
building 'fib' extension
|
||
creating build
|
||
creating build\temp.win-amd64-2.7
|
||
creating build\temp.win-amd64-2.7\Release
|
||
C:\Miniconda\Scripts\gcc.bat -DMS_WIN64 -mdll -O -Wall -IC:\Miniconda\include -IC:\Miniconda\PC -c fib.c -o build\temp.win-amd64-2.7\Release\fib.o
|
||
writing build\temp.win-amd64-2.7\Release\fib.def
|
||
C:\Miniconda\Scripts\gcc.bat -DMS_WIN64 -shared -s build\temp.win-amd64-2.7\Release\fib.o build\temp.win-amd64-2.7\Release\fib.def -LC:\Miniconda\libs -LC:\Miniconda\PCbuild\amd64 -lpython27 -lmsvcr90 -o "C:\Users\Jin\Documents\Git\python-tutorial\07\. interfacing with other languages\fib.pyd"
|
||
|
||
```
|
||
|
||
使用模块:
|
||
|
||
In [7]:
|
||
|
||
```py
|
||
import fib
|
||
|
||
fib.cyfib(10)
|
||
|
||
```
|
||
|
||
Out[7]:
|
||
|
||
```py
|
||
144
|
||
```
|
||
|
||
In [8]:
|
||
|
||
```py
|
||
import zipfile
|
||
|
||
f = zipfile.ZipFile('07-03-fib.zip','w',zipfile.ZIP_DEFLATED)
|
||
|
||
names = 'fib.pyd fib.pyx fib.c setup.py'.split()
|
||
for name in names:
|
||
f.write(name)
|
||
|
||
f.close()
|
||
|
||
```
|
||
|
||
## 使用 pyximport
|
||
|
||
清理之前生成的文件:
|
||
|
||
In [9]:
|
||
|
||
```py
|
||
!rm -f fib.pyd
|
||
!rm -f fib.pyc
|
||
!rm -f fib.C
|
||
|
||
```
|
||
|
||
清理之前导入的模块:
|
||
|
||
In [10]:
|
||
|
||
```py
|
||
%reset -f
|
||
|
||
```
|
||
|
||
使用 `pyximport`:
|
||
|
||
In [11]:
|
||
|
||
```py
|
||
import pyximport
|
||
pyximport.install()
|
||
|
||
import fib
|
||
|
||
fib.cyfib(10)
|
||
|
||
```
|
||
|
||
Out[11]:
|
||
|
||
```py
|
||
144
|
||
```
|
||
|
||
`install` 函数会自动检测 Cython 程序的变化,并自动导入,不过一般用于简单文件的编译。
|
||
|
||
清理生成的文件:
|
||
|
||
In [12]:
|
||
|
||
```py
|
||
!rm -f setup*.*
|
||
!rm -f fib.*
|
||
!rm -rf build
|
||
|
||
``` |