Cython 的本质可以总结如下:Cython 是包含 C 数据类型的 Python。
Cython 是 Python:几乎所有 Python 代码都是合法的 Cython 代码。 (存在一些限制,但是差不多也可以。) Cython 的编译器会转化 Python 代码为 C 代码,这些 C 代码均可以调用 Python/C 的 API。
要使用cython, 先要配置c编译器,在windows中配置比较麻烦,所以在wsl中使用gcc容器。
-
下载安装cython
C:\Users\lt\AppData\Local\Programs\Python\Python313>wsl
root@DESKTOP-59T6U68:/mnt/c/Users/lt/AppData/Local/Programs/Python/Python313# docker start gcc
gcc
root@DESKTOP-59T6U68:/mnt/c/Users/lt/AppData/Local/Programs/Python/Python313# docker exec -it gcc bash
root@6ae32a5ffcde:/# cd /parroot@6ae32a5ffcde:/par# python3 pip.pyz download cython -d 313
Looking in indexes: https://mirrors.aliyun.com/pypi/simple
Collecting cython
Downloading https://mirrors.aliyun.com/pypi/packages/ac/25/58893afd4ef45f79e3d4db82742fa4ff874b936d67a83c92939053920ccd/cython-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (3.4 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.4/3.4 MB 18.7 MB/s eta 0:00:00
Saved ./313/cython-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Successfully downloaded cythonroot@6ae32a5ffcde:/par# python3 pip.pyz install cython -f 313 --no-index --break-system-packages
Looking in links: 313
Processing ./313/cython-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Installing collected packages: cython
Successfully installed cython-3.2.4
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning. -
编写源代码和setup.py
按照旧版文档 https://moonlet.gitbooks.io/cython-document-zh_cn/content/ch1-basic_tutorial.html的说明,编写:
helloworld.pyx
python
print ("Hello World")
python
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("helloworld.pyx")
)
编译扩展
root@6ae32a5ffcde:/par# python3 setup.py build_ext --inplace
/par/setup.py:1: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
from distutils.core import setup
Compiling helloworld.pyx because it changed.
[1/1] Cythonizing helloworld.pyx
running build_ext
building 'helloworld' extension
creating build
creating build/temp.linux-x86_64-3.11
x86_64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.11 -c helloworld.c -o build/temp.linux-x86_64-3.11/helloworld.o
helloworld.c:31:10: fatal error: Python.h: No such file or directory
31 | #include "Python.h"
| ^~~~~~~~~~
compilation terminated.
error: command '/usr/local/bin/x86_64-linux-gnu-gcc' failed with exit code 1
root@6ae32a5ffcde:/par# apt install python-dev
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Package python-dev is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
python-dev-is-python3
N: Ignoring file 'debian.sources_org' in directory '/etc/apt/sources.list.d/' as it has an invalid filename extension
E: Package 'python-dev' has no installation candidate
root@6ae32a5ffcde:/par# apt install python3-dev
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
libjs-jquery libjs-sphinxdoc libjs-underscore libpython3-dev libpython3.11 libpython3.11-dev python3.11-dev
The following NEW packages will be installed:
libjs-jquery libjs-sphinxdoc libjs-underscore libpython3-dev libpython3.11 libpython3.11-dev python3-dev
python3.11-dev
0 upgraded, 8 newly installed, 0 to remove and 117 not upgraded.
Need to get 7952 kB of archives.
After this operation, 36.3 MB of additional disk space will be used.
N: Ignoring file 'debian.sources_org' in directory '/etc/apt/sources.list.d/' as it has an invalid filename extension
Do you want to continue? [Y/n]
Get:1 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 libjs-jquery all 3.6.1+dfsg+~3.5.14-1 [326 kB]
Get:2 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 libjs-underscore all 1.13.4~dfsg+~1.11.4-3 [116 kB]
Get:3 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 libjs-sphinxdoc all 5.3.0-4 [130 kB]
Get:4 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 libpython3.11 amd64 3.11.2-6+deb12u6 [1987 kB]
Get:5 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 libpython3.11-dev amd64 3.11.2-6+deb12u6 [4742 kB]
Get:6 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 libpython3-dev amd64 3.11.2-1+b1 [9572 B]
Get:7 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 python3.11-dev amd64 3.11.2-6+deb12u6 [615 kB]
Get:8 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 python3-dev amd64 3.11.2-1+b1 [26.2 kB]
Fetched 7952 kB in 1s (8753 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libjs-jquery.
(Reading database ... 64928 files and directories currently installed.)
Preparing to unpack .../0-libjs-jquery_3.6.1+dfsg+~3.5.14-1_all.deb ...
Unpacking libjs-jquery (3.6.1+dfsg+~3.5.14-1) ...
Selecting previously unselected package libjs-underscore.
Preparing to unpack .../1-libjs-underscore_1.13.4~dfsg+~1.11.4-3_all.deb ...
Unpacking libjs-underscore (1.13.4~dfsg+~1.11.4-3) ...
Selecting previously unselected package libjs-sphinxdoc.
Preparing to unpack .../2-libjs-sphinxdoc_5.3.0-4_all.deb ...
Unpacking libjs-sphinxdoc (5.3.0-4) ...
Selecting previously unselected package libpython3.11:amd64.
Preparing to unpack .../3-libpython3.11_3.11.2-6+deb12u6_amd64.deb ...
Unpacking libpython3.11:amd64 (3.11.2-6+deb12u6) ...
Selecting previously unselected package libpython3.11-dev:amd64.
Preparing to unpack .../4-libpython3.11-dev_3.11.2-6+deb12u6_amd64.deb ...
Unpacking libpython3.11-dev:amd64 (3.11.2-6+deb12u6) ...
Selecting previously unselected package libpython3-dev:amd64.
Preparing to unpack .../5-libpython3-dev_3.11.2-1+b1_amd64.deb ...
Unpacking libpython3-dev:amd64 (3.11.2-1+b1) ...
Selecting previously unselected package python3.11-dev.
Preparing to unpack .../6-python3.11-dev_3.11.2-6+deb12u6_amd64.deb ...
Unpacking python3.11-dev (3.11.2-6+deb12u6) ...
Selecting previously unselected package python3-dev.
Preparing to unpack .../7-python3-dev_3.11.2-1+b1_amd64.deb ...
Unpacking python3-dev (3.11.2-1+b1) ...
Setting up libpython3.11:amd64 (3.11.2-6+deb12u6) ...
Setting up libpython3.11-dev:amd64 (3.11.2-6+deb12u6) ...
Setting up libjs-jquery (3.6.1+dfsg+~3.5.14-1) ...
Setting up libjs-underscore (1.13.4~dfsg+~1.11.4-3) ...
Setting up libpython3-dev:amd64 (3.11.2-1+b1) ...
Setting up python3.11-dev (3.11.2-6+deb12u6) ...
Setting up libjs-sphinxdoc (5.3.0-4) ...
Setting up python3-dev (3.11.2-1+b1) ...
Processing triggers for libc-bin (2.36-9+deb12u13) ...
编译出错了,在网上查到需要安装python-dev,实际上,对于python3,要安装python3-dev,再次编译,当前目录下生成一个helloworld.c和helloworld.cpython-311-x86_64-linux-gnu.so文件。
root@6ae32a5ffcde:/par# python3 setup.py build_ext --inplace
/par/setup.py:1: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
from distutils.core import setup
running build_ext
building 'helloworld' extension
x86_64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.11 -c helloworld.c -o build/temp.linux-x86_64-3.11/helloworld.o
x86_64-linux-gnu-gcc -shared -Wl,-O1 -Wl,-Bsymbolic-functions -g -fwrapv -O2 -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.11/helloworld.o -o /par/helloworld.cpython-311-x86_64-linux-gnu.so
root@6ae32a5ffcde:/par# python3
Python 3.11.2 (main, Apr 28 2025, 14:11:48) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import helloworld
Hello World
>>>
在python中import ,就执行了。
再按照新版文档 https://cython.readthedocs.io/en/stable/src/tutorial/cython_tutorial.html#fibonacci-fun 的说明,建立:
fibonacci.pyx
python
def fib(n):
"""Print the Fibonacci series up to n."""
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a + b
print()
python
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("fibonacci.pyx"),
)
编译插件
root@6ae32a5ffcde:/par# python3 setup1.py build_ext --inplace
Traceback (most recent call last):
File "/par/setup1.py", line 1, in <module>
from setuptools import setup
ModuleNotFoundError: No module named 'setuptools'
root@6ae32a5ffcde:/par# pip download setuptools -d 313
bash: pip: command not found
root@6ae32a5ffcde:/par# python3 pip.pyz download setuptools -d 313
Looking in indexes: https://mirrors.aliyun.com/pypi/simple
Collecting setuptools
Downloading https://mirrors.aliyun.com/pypi/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl (1.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.0/1.0 MB 1.8 MB/s eta 0:00:00
Saved ./313/setuptools-82.0.1-py3-none-any.whl
Successfully downloaded setuptools
root@6ae32a5ffcde:/par# python3 pip.pyz install setuptools -f 313 --no-index --break-system-packages
Looking in links: 313
Processing ./313/setuptools-82.0.1-py3-none-any.whl
Installing collected packages: setuptools
Successfully installed setuptools-82.0.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
root@6ae32a5ffcde:/par# python3 setup1.py build_ext --inplace
Compiling fibonacci.pyx because it changed.
[1/1] Cythonizing fibonacci.pyx
running build_ext
building 'fibonacci' extension
creating build/temp.linux-x86_64-cpython-311
x86_64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/include/python3.11 -c fibonacci.c -o build/temp.linux-x86_64-cpython-311/fibonacci.o
creating build/lib.linux-x86_64-cpython-311
x86_64-linux-gnu-gcc -shared -Wl,-O1 -Wl,-Bsymbolic-functions -g -fwrapv -O2 build/temp.linux-x86_64-cpython-311/fibonacci.o -L/usr/lib/x86_64-linux-gnu -o build/lib.linux-x86_64-cpython-311/fibonacci.cpython-311-x86_64-linux-gnu.so
copying build/lib.linux-x86_64-cpython-311/fibonacci.cpython-311-x86_64-linux-gnu.so ->
新版的文档用到的setuptools模块需要安装,安装后就可以编译成功了。import fibonacci是建立fib函数,然后用fibonacci.fib()调用就可以了。
root@6ae32a5ffcde:/par# python3
Python 3.11.2 (main, Apr 28 2025, 14:11:48) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import fibonacci
>>> fibonacci.fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
再用一个计算质数的程序来比较cython和python的效率,编译的so大约比原始py文件快了20%。
root@6ae32a5ffcde:/par# python3 setup2.py build_ext --inplace
Compiling primes.py because it changed.
[1/1] Cythonizing primes.py
warning: primes.py:75:29: Item lookup of unicode character codes now always converts to a Unicode string. Use an explicit C integer cast to get back the previous integer lookup behaviour.
warning: primes.py:76:32: Item lookup of unicode character codes now always converts to a Unicode string. Use an explicit C integer cast to get back the previous integer lookup behaviour.
running build_ext
building 'primes' extension
x86_64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/include/python3.11 -c primes.c -o build/temp.linux-x86_64-cpython-311/primes.o
x86_64-linux-gnu-gcc -shared -Wl,-O1 -Wl,-Bsymbolic-functions -g -fwrapv -O2 build/temp.linux-x86_64-cpython-311/primes.o -L/usr/lib/x86_64-linux-gnu -o build/lib.linux-x86_64-cpython-311/primes.cpython-311-x86_64-linux-gnu.so
copying build/lib.linux-x86_64-cpython-311/primes.cpython-311-x86_64-linux-gnu.so ->
root@6ae32a5ffcde:/par# python3
Python 3.11.2 (main, Apr 28 2025, 14:11:48) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import primes
>>>
root@6ae32a5ffcde:/par# time python3 -c "import primes"
real 0m1.846s
user 0m1.687s
sys 0m0.199s
mv primes.cpython-311-x86_64-linux-gnu.so primes.cpython-311-x86_64-linux-gnu.so.old
root@6ae32a5ffcde:/par# time python3 -c "import primes"
real 0m2.271s
user 0m2.074s
sys 0m0.222s