cython编译加密python源码

32 篇文章 0 订阅
场景
python的解释特性是将py编译为独有的二进制编码pyc 文件,然后对pyc中的指令进行解释执行,但是 pyc的反编译却非常简单,可直接反编译为源码,当需要将产品发布到外部环境的时候,源码的保护尤为重要。

一、Cpython介绍

Cython是一个编程语言,它通过类似Python的语法来编写C扩展并可以被Python调用,既具备了Python快速开发的特点,又可以让代码运行起来像C一样快,同时还可以方便地调用C library。
Cython是属于python的超集,用于编写python的c扩展语言
  
pyx文件由 Cython 编译为.c文件,包含 python 扩展模块的代码。.c文件由 C 编译器编译为.so文件(或 Windows 上的.pyd)。
生成的.so文件或pyd文件是D语言(C/C++综合进化版本)生成的二进制文件,理论上很难反编译。

Note: 纯python源码被cython编译后,因为没有使用类型标注等cython语法,故编译后的动态链接库和可执行文件,主要依赖python的运行时,并不依赖C/C++运行时,主要由python解释器执行,多线程GIL的问题同样存在,性能提升有限,但对for循环、大的列表对象遍历性能有明显优化效果。
优势:资源丰富,适合快速开发。翻译成C后速度比较快
缺陷:无法支持JIT技术(导致纯python的执行速度比JAVA、JAVASCRIPT等要慢,于是有了PyPy)

二、安装

# 安装cython
pip3 install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple cython
# 安装c编译器(linux需安装python-devel, gcc
centos: yum install python-devel  gcc
ubuntu: apt-get install build-essential

三、使用方法

先用cython将python语言代码转换为c语言代码,然后用c编译器(gcc)生成可执行文件或动态链接库
   
通过 shell 或  python脚本的方式 ,将项目启动的入口py编译成可执行文件,将项目的其他.py文件编译成.so(__init__.py除外)
Note: __init__.py文件定义了python的包结构, 为了使cython编译后的.so 能按照正常路径import,__init__.py不能被编译 ,故为了保护代码,整个项目的所有__init__.py文件不建议放业务相关代码。
  

3.1、单个文件的编译示例-linux

目录结构如下:
test/
├── test.py
├── main.py
test.py:
def hello():
    print('hello!')
main.py:
#!/usr/bin/python3.8
from test import hello

if __name__ == "__main__":
    hello()

3.1.1、将启动main.py编译成二进制可执行文件main

# 可通过文件头的 #!/usr/bin/env python 标记是否程序启动文件
   
>>>python3版本下#!/usr/bin/python3.8
main.py ---> main.c ---> main.o ---> main
# step1: python代码翻译成c代码(main.py -> main.c
cython -D -3 --directive always_allow_keywords=true --embed main.py
    
# step2: c代码编译为目标文件(main.c -> main.o
gcc -c main.c -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o main.o
   
# step3: 将目标文件编译为二进制可执行文件(main.o -> main
gcc main.o -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o main
main.py ---> main.c ---> main
# step1: python代码翻译成c代码(main.py -> main.c
cython -D -3 --directive always_allow_keywords=true --embed main.py
      
# step2: 将c代码编译为二进制可执行文件(main.c -> main
gcc main.c -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o main

3.1.2、将test.py编译为动态链接库test.so

>>>python3版本下test.py ---> test.c ---> test.so
# step1: python代码翻译成c代码(test.py -> test.c
cython -D -3 --directive always_allow_keywords=true test.py
    
# step2: c代码编译为linux动态链接库文件(test.c -> test.so
gcc test.c -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o test.so
cython参数说明:
-D, --no-docstrings, Strip docstrings from the compiled module.

-o, --output-file <filename>   Specify name of generated C file
-2                             Compile based on Python-2 syntax and code semantics.
-3                             Compile based on Python-3 syntax and code semantics.
gcc参数说明:
-shared:
编译动态库时要用到

-pthread:
在Linux中要用到多线程时,需要链接pthread库

-fPIC:
作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意
位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

-fwrapv:
它定义了溢出时候编译器的行为——采用二补码的方式进行操作

-O参数
这是一个程序优化参数,一般用-O2就是,用来优化程序用的
-O2:
会尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间。
-O3: 在O2的基础上进行更多的优化

-Wall:
编译时 显示Warning警告,但只会显示编译器认为会出现错误的警告

-fno-strict-aliasing:
“-fstrict-aliasing”表示启用严格别名规则,“-fno-strict-aliasing”表示禁用严格别名规则,当gcc的编译优化参数为“-O2”、“-O3”和“-Os”时,默认会打开“-fstrict-aliasing”。

-I (大写的i):
是用来指定头文件目录
-I /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录,寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include

-l:
-l(小写的 L)参数就是用来指定程序要链接的库,-l参数紧接着就是库名,把库文件名的头lib和尾.so去掉就是库名了,例如我们要用libtest.so库库,编译时加上-ltest参数就能用上了

3.2、单个文件的编译示例-windows

windows系统使用cython需要确保 已安装C/C++编译器且环境变量正确配置,cython能找到编译器。windows系统可使用MSVC(Microsoft Visual C/C++)或者clang编译器。
    
将test.py编译为动态链接库test.pyd:
>>>python3版本下test.py ---> test.c ---> test.pyd
# step1: 将python代码翻译成c代码(test.py -> test.c)
cython -D -3 --directive always_allow_keywords=true test.py
    
# step2: 将c代码编译为windows动态链接库文件(test.c -> test.pyd)
cythonize -i test.c
最后得到windows下的动态链接库文件test.cp39-win_amd64.pyd,还需要将文件名重命名为test.pyd。
cythonize参数说明:
-b, --build     build extension modules using distutils
-i, --inplace   build extension modules in place using distutils(implies -b),即将编译后的扩展模块直接放在与test.py同级的目录中。

四、python编译可执行文件与动态链接库

五、参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值