cython编译Python为c语言

本文最后更新于 2023年9月25日。

第一种办法:

  • 执行命令:cython test.py
  • 结果:会在同一目录下面生成test.c文件
  • 执行命令: gcc -c -fPIC -I /usr/include/python2.7 test.c
  • 结果: 在同一目录下面生成test.o文件
  • 执行命令: gcc -shared test.o -c test.so
  • 结果: 在同一目录下面生成test.so文件

最后,生成的test.so文件就是需要的文件

第二种办法:

[setup.py]
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = "test",
ext_modules = cythonize("test.py")
)
  • 执行命令: python setup.py build_ext –inplace

第二种办法是对单独文件进行编译,下面介绍一种批量的办法:

#-*- coding:utf-8 -*-_
import os
import re
from distutils.core import Extension, setup
from Cython.Build import cythonize
from Cython.Compiler import Options
# __file__ 含有魔术变量的应当排除,Cython虽有个编译参数,但只能设置静态。
exclude_so = ['__init__.py', 'run.py']
sources = 'backend'
extensions = []
remove_files = []
for source,dirnames,files in os.walk(sources):
for dirpath, foldernames, filenames in os.walk(source):
if 'test' in dirpath:
break;
for filename in filter(lambda x: re.match(r'.*[.]py$', x), filenames):
file_path = os.path.join(dirpath, filename)
if filename not in exclude_so:
extensions.append(
Extension(file_path[:-3].replace('/', '.'), [file_path], extra_compile_args = ["-Os", "-g0"],
extra_link_args = ["-Wl,--strip-all"]))
remove_files.append(file_path[:-3]+'.py')
remove_files.append(file_path[:-3]+'.pyc')
Options.docstrings = False
compiler_directives = {'optimize.unpack_method_calls': False, 'always_allow_keywords': True}
setup(
# cythonize的exclude全路径匹配,不灵活,不如在上一步排除。
ext_modules = cythonize(extensions, exclude = None, nthreads = 20, quiet = True, build_dir = './build',
language_level = 2, compiler_directives = compiler_directives))
# 删除py和pyc文件
for remove_file in remove_files:
if os.path.exists(remove_file):
os.remove(remove_file)
  • 执行命令: python setup.py build_ext –inplace
  • 结果:最后生成.so文件,删除中间结果。

重点提一下,在编译flask代码时,遇到问题,报错:参数不够(大体意思是这样,错误未截图),在compiler_directives中添加: {always_allow_keywords:True}

正如我先前所说,你需要像这样运行Cython编译器。

cython <cython_file> --embed

要用gcc编译,你需要找到python头文件在你的系统上的位置(你可以通过运行distutils.sysconfig.get_python_inc()得到这个位置(你必须先导入它)。 它可能只是你的Python安装目录中的/include子目录。

你还必须找到Python共享库。 对于Python 2.7,在Windows上是libpython27.a,在Linux上是libpython2.7.so

然后你的gcc命令将是

gcc <C_file_from_cython> -I<include_directory> -L<directory_containing_libpython> -l<name_of_libpython_without_lib_on_the_front> -o <output_file_name>

包括-fPIC标志可能是明智的。 在Windows 64位机器上,你还必须包括-D MS_WIN64标志,告诉mingw为64位Windows编译。

如果你正在编译依赖于NumPy的东西,你还需要包括包含NumPy头文件的目录。 你可以通过运行numpy.get_include()找到这个文件夹(同样,在导入numpy之后)。 然后你的gcc命令就变成了

gcc <C_file_from_cython> -I<include_directory> -I<numpy_include_directory> -L<directory_containing_libpython> -l<name_of_libpython_without_lib_on_the_front> -o <output_file_name>

这个gcc命令选项guide可能会有帮助。