cython编译加密python源码

news/2024/11/28 8:29:16/
场景
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 helloif __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编译可执行文件与动态链接库

五、参考

(8条消息) python性能优化和源码保护-编译整个项目_python编译当前项目_pushiqiang的博客-CSDN博客
(2条消息) gcc编译_青霄的博客-CSDN博客
Cython: C-Extensions for Python
Cython的简单使用 - 小得盈满 - 博客园 (cnblogs.com) 
cython编译的so和c语言编译的so本质上有什么区别? - 知乎 (zhihu.com)
github: 使用Cython编译整个python项目

http://www.ppmy.cn/news/88411.html

相关文章

【强制缓存和协商缓存的区别】

超文本传输协议&#xff08;HyperText Transfer Protocol&#xff0c;HTTP&#xff09;是目前使用最广泛的应用层协议。在网站、App、开放接口中都可以看到它。HTTP 协议设计非常简单&#xff0c;但是涵盖的内容很多。 WWW 1990 年蒂姆伯纳斯李开发了第一个浏览器&#xff0c…

Flutter控件之CircularProgressIndicator

CircularProgressIndicator的作用 Flutter中的CircularProgressIndicator是一个圆形进度指示器&#xff0c;用于表示正在进行的任务的进度。它通常用于长时间运行的任务&#xff0c;例如文件下载、网络请求等。CircularProgressIndicator可以在圆周上旋转&#xff0c;以表示正…

大数据开发之Hive案例篇8-解析XML

文章目录 一. 问题描述二. 解决方案2.1 官方文档2.2 XML格式不规范 一. 问题描述 今天接到一个新需求&#xff0c;hive表里面有个字段存储的是XML类型数据 数据格式: <a><b>bb</b><c>cc</c> </a>二. 解决方案 2.1 官方文档 遇到不懂的…

数据库概述

文章目录 基本概念一、数据1.定义2.分类 二、数据库1.定义2.三个基本特点&#xff1a; 三、数据库管理系统(DBMS)1.定义2.功能3.特色 四、数据管理技术的产生和发展1.人工管理阶段&#xff1a;2.文件系统阶段3.数据库系统阶段 五、数据库系统的特点1.数据结构化2.数据的共享性高…

什么是DRTP?在证券行业的应用?

一、概念 DRTP是指分布式实时处理&#xff08;Distributed Real-Time Processing&#xff09;&#xff0c;是一种处理实时数据的技术。它通过将数据分散到多个节点上进行处理&#xff0c;从而实现高效的实时数据处理。DRTP通常用于处理大规模的数据流&#xff0c;例如网络流量…

Python pathlib模块

pathlib 模块提供了表示文件系统路径的类&#xff0c;可适用于不同的操作系统。使用 pathlib 模块&#xff0c;相比于 os 模块可以写出更简洁&#xff0c;易读的代码。pathlib 模块中的 Path 类继承自 PurePath&#xff0c;对 PurePath 中的部分方法进行了重载&#xff0c;相比…

RESTful接口设计规范

RESTful是目前最流行的API设计规范&#xff0c;它是用于Web数据接口的设计。从字面可以看出&#xff0c;他是Rest式的接口&#xff0c;所以我们先了解下什么是Rest。 REST与技术无关&#xff0c;它代表的是一种软件架构风格&#xff0c;REST它是 Representational State Trans…

【leetcode】Find Median From Data Stream

参考资料&#xff1a;左神算法课《剑指offer》 295. Find Median from Data Stream The median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value, and the median is the mean of the two middle values. For ex…