Python扩展三种不同的实现方式:
一、编写纯C扩展。
写过JNI的人很容易理解,纯C扩展就是利用Python/C API来扩展python应用。C/API的详细使用,请参见: https://docs.python.org/3.6/c-api/
例子:
"""setup.py文件:用来告诉解释器我们的扩展是如何编译的
扩展的构建过程可以通过Python的setup.py构建命令初始化,并且它会在程序包安装时自动执行
"""
from setuptools import setup, Extension
setup(
name='fibonacci',
ext_modules=[
Extension('fibonacci', ['fibonacci.c']),
]
)
"""fibonacci.c文件"""
#Python.h把整个Python/C API以及编写扩展需要引入的一切包含进来
#include <Python.h>
long long fibonacci(unsigned int n) {
if (n < 2) {
return 1;
} else {
return fibonacci(n-2) + fibonacci(n-1);
}
}
static PyObject* fibonacci_py(PyObject* self, PyObject* args) {
PyObject *result = NULL;
long n;
if (PyArg_ParseTuple(args, "l", &n)) {
result = Py_BuildValue("L", fibonacci((unsigned int)n));
}
return result;
}
static char fibonacci_docs[] =
"fibonacci(n): Return nth Fibonacci sequence number "
"computed recursively\n";
static PyMethodDef fibonacci_module_methods[] = {
{"fibonacci", (PyCFunction)fibonacci_py,
METH_VARARGS, fibonacci_docs},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef fibonacci_module_definition = {
PyModuleDef_HEAD_INIT,
"fibonacci",
"Extension module that provides fibonacci sequence function",
-1,
fibonacci_module_methods
};
PyMODINIT_FUNC PyInit_fibonacci(void) {
Py_Initialize();
return PyModule_Create(&fibonacci_module_definition);
}
二、使用Cython
Cython既是一个优化的静态编译器,也是一个Python的超集编程语言的名称。作为编译器,它可以使用Python/C API执行源到源的编译,把Python代码及其Cython方言编译为Python C扩展。它允许你结合Python和C的威力,而不需要手动处理Python/C API。
2.1 Cython作为源码编译器
setup.py脚本文件
from setuptools import setup
from Cython.Build import cythonize
setup(
name='fibonacci',
ext_modules=cythonize(['fibonacci.pyx'])
)
Cython源文件:fibonacci.pyx
"""Cython module that provides fibonacci sequence function"""
cdef long long fibonacci_cc(unsigned int n):
if n < 2:
return n
else:
return fibonacci_cc(n - 1) + fibonacci_cc(n - 2)
def fibonacci(unsigned int n):
""" Return nth Fibonacci sequence number computed recursively
"""
return fibonacci_cc(n)
使用以下命令启用可选的Cython依赖与编译器:
$ USE_CYTHON=1 pip install .[with-cython]
2.1 Cython作为一门语言
"""Python module that provides fibonacci sequence function"""
def fibonacci(n):
""" Return nth Fibonacci sequence number computed recursively
"""
if n < 2:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
from setuptools import setup
from Cython.Build import cythonize
setup(
name='fibonacci',
ext_modules=cythonize(['fibonacci.py'])
)
相比于将Cython作为编译器,唯一真正改变是的fibonacci函数的签名。
三、使用Pyrex
Pyrex 是一种专门设计用来编写 Python 扩展模块的语言。根据 Pyrex Web 站点的介绍,“它被设计用来在友好易用的高级 Python 世界和凌乱的低级 C 世界之间搭建一个桥梁。”虽然几乎所有的 Python 代码都可以作为有效的 Pyrex 代码使用,但是您可以在 Pyrex 代码中添加可选的静态类型声明,从而使得这些声明过的对象以 C 语言的速度运行。