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 語言的速度運行。