Cython编译python文件

一、简介

Cython是一个快速生成Python扩展模块的工具,从语法层面上来讲是Python语法和C语言语法的混血,当Python性能遇到瓶颈时,Cython直接将C的原生速度植入Python程序,这样使Python程序无需使用C重写,能快速整合原有的Python程序,这样使得开发效率和执行效率都有很大的提高,而这些中间的部分,都是Cython帮我们做了.

首先Cython官网地址是:http://cython.org/ 这里有cython的安装和开发文档,关于Cython的下载可以在pypi上直接下载安装包:https://pypi.python.org/pypi/Cython/ 由于是在Linux下安装使用,这里下载的是Cython-0.25.2.tar.gz,上传至linux执行如下步骤安装:

tar -xvzf Cython-0.25.2.tar.gz
cd Cython-0.25.2
python setup.py install

也可以直接用anaconda安装

pip install cython

二、cython 编译

cython编译工具存在两个命令行工具cython和cythonize

  • --include-dir:指定编译时包含的C/C++头文件或其他.py或.pyx文件

  • --output-file:指定解析后的C/C++源代码文件的所在路径 --inplace 表示放在源文件旁边

  • --working:指定cython解析器的工作目录

  • -2或-3:-2告知cython解析器以python2的方式理解python源代码,-3告知cython解析器以python3的方式去理解python源代码

    image-20210809103513643.png

    我们使用以下指令将python3的primer.pyx的源代码转换为C代码,如下图所示

cython primer.pyx -o ./src/primer.c -3

生成c代码后,就可以使用gcc 把c代码转为动态库so文件

gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing \
      -I/usr/include/python3.6 -o ./primer.so  ./primer.c

三、cythonize编译

cythonize -a -i primer.pyx

这将创建一个primer.c文件(或在C ++模式下为primer.cpp),对其进行编译,

  • 并将生成的扩展模块(.so或.pyd,具体取决于您的平台)从下图可知在当前目录生成了C/C++源文件和扩展模块。
  • -a开关还会生成带注释的源代码html文件。

编译后,会将primer.cpython-36m-x86_64-linux-gnu(对于Windows可能为primer.cpython-36m-win64.pyd)文件写入目标目录,并且可以将您的模块primer.cpython-36m-x86_64-linux-gnu与其他任何Python模块一样导入。

四、使用setup.py编译

根据一个多个源文件,使用到cv2跟numpy库的例子讲解

4.1 创建源文件hello.py

def print_hello(name):
    print("你好呀,%s"%name)

4.2 创建源文件add.pyx

先创建一个tool文件夹,在此文件夹下新建add.pyx

import numpy as np
import cv2
def img_shape(path):
    img = cv2.imread(path)
    shape = img.shape
    return shape
def creat_array(num):
    data = np.ones(num)
    return data

4.3 创建编译文件setup.py

Python 有一个标准库 disutils,可以用来构建、打包、分发 Python 工程。而其中一个对我们有用的特性就是它可以借助 C 编译器将 C 源码编译成扩展模块,并且这个模块是自带的、考虑了平台、架构、Python 版本等因素,因此我们在任意地方使用disutils都可以得到扩展模块。

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
filename1 = 'hello'  # 源文件名
full_filename1 = 'hello.py'  # 包含后缀的源文件名
filename2 = 'tool.add'
full_filename2 ='tool/add.pyx'
extensions=[
 Extension(filename1, [full_filename1]),  # 配置需要cython编译的源文件
 Extension(filename2, [full_filename2]),
]
# 如果只有一个文件,直接extension=Extension()即可
setup(
 name ='test',    # 可以省略
 cmdclass={'build_ext':build_ext}, #可以省略
 ext_modules=cythonize(extensions,language_level=3),   #指定python3
)

Extension()参数

  • name="filename", 生成扩展模块的名字,即import 对应的名字

  • sources=[file_path] 源文件地址

如果您的构建以setup.py方式直接依赖于Cython,那么您编译的扩展需要打算分享到pip库可能还想告知pip,你扩展库的和其他扩展的依赖关系,请执行PEP 518https://www.python.org/dev/peps/pep-0518,Cython是setup.py执行所必需,创建一个pyproject.toml文件,其中至少包含:

[build-system]
requires = ["setuptools", "wheel", "Cython"]

4.4 进行编译

python setup.py build_ext --inplace
  • build_ext 表示把c文件打包为动态库so文件,如果没有此参,只会生成.c文件
  • --inplace 表示把编译后的文件放在源文件旁边
    如果后续有修改,只需要对其中一个文件编译,按第三条 cythonize编译即可.


    image-20210809105157568.png

    生成的so文件可以重命名,不影响导入

直接改为add.so 跟hello.so

4.5 测试

编写测试代码test.py

from hello import print_hello
from tool.add import *
import cv2
import numpy as np
print_hello("yangjain")
shape = img_shape('test.jpg')
print("shape=",shape)
data = creat_array(3)
print("data=\n",data)
python test.py

结果如下

你好呀,yangjain
shape= (556, 446, 3)
data=
 [1\. 1. 1.]

注意点:

1.子文件夹内的文件最好不要互相调用,在调so文件时,会导致提示找不到包. 即子文件夹内的文件最好为单独的工具包文件,只可导入python pip 里的包.

2.用什么环境生成的so文件,就必须在那个环境中运行,否则提示找不到包. 所以在宿主机生成的so文件无法在docker容器中运行.

[参考]

第4篇:Cython编译细节详解 - 知乎 (zhihu.com)

《Cython系列》2. 编译并运行 Cython 代码的几种方式 - 古明地盆 - 博客园 (cnblogs.com)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容