引言
前面的文章提到了使用 Pyarmor 来保护自己的 Python 代码,Pyarmor 通过加密源代码来保护我们的代码。但是Pyarmor 是收费的,即使是有免费许可证,但是大批量使用的话还是一笔不小的成本,在不需要许可证机制保护代码的情况下可以考虑使用 Cython 来保护我们的 Python 代码。
Cython
Cython 是一种编程语言,它是 Python 的超集,允许开发者在 Python 代码中嵌入 C 语言的特性。Cython 主要用于提高 Python 代码的执行速度,同时也可以将 Python 代码编译为 C 扩展模块,从而增加代码的保护性。
Cython 安装
Cython 的安装很简单,直接使用 pip 安装就可以,我这里使用 poetry 来安装依赖。由于 Cython 会将 Python 代码编译为本地机器码,所以在使用 Cython 进行编译时,需要使用到当前平台的编译器。由于我使用 Mac,系统已经自带了,所以这里不需要重复安装了,如果使用 Windows 系统的话需要安装 C++编译器。
poetry add cython
# or
pip install cython
示例脚本
这里先准备一个示例脚本,脚本会做一个累加计算,并且访问百度获取响应。
# cython_test.py
import time
from contextlib import contextmanager
import requests
def sum_of_squares_cython(int_list):
n = len(int_list)
result = 0
for i in range(n):
result += int_list[i] ** 2
return result
def get_response():
return requests.get('https://www.baidu.com').text[:100]
@contextmanager
def timer():
t = time.time()
yield
print(f'运行时间为:{time.time() - t:.4f}')
# demo.py
from cython_test import get_response, sum_of_squares_cython, timer
if __name__ == '__main__':
with timer():
print(sum_of_squares_cython([a for a in range(1000000)]))
print(get_response())
运行以上代码,得到以下结果:
333332833333500000
运行时间为:0.2355
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charse
编译
创建 setup.py ,执行编译指令。
# setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name='test_cython_project',
ext_modules=cythonize("cython_demo/cython_test.py", language_level=3),
)
使用以下代码编译代码:
python cython_demo/setup.py build_ext --inplace
编译完成后,可以看到文件夹内生成了对应的 c 文件和 Mac 平台的 so 文件。c 文件有一万多行,这个时候调用 so 文件就可以不再需要解释器了,运行的就是本地的机器码,会快很多。
测试运行结果
将之前的cython_test.py删除或者改名,让 Python 无法找到它,不然 Python 会重新导入它。然后Python 就会导入对应的 so 文件, so 文件其实和 Python 模块是一样的,可以直接当做模块调用,代码都不用改。
改完名后,重新运行之前的代码:
333332833333500000
运行时间为:0.2133
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charse
从累加的时间上来看,大概比之前运行快了 0.02 秒吧,而且多次运行也很稳定,达到了加速代码运行的目的。
编译产物
而且编译产物是 so 文件,这个文件是二进制的,现在好多 Python 的依赖模块都是通过 Cython 编译的,并且在分发依赖的时候分发的就是 so 或者 pyd 文件,这样主要是为了加快 Python 原生代码的运行速度。
查看 so 文件:
可以发现,编译后的 so 文件的确是苹果系统的可执行文件,和 Windows 上的 pyd 文件是一样的。
Cython 模块分发
Cython 模块编译后,编译产物是二进制文件,如果要分发的话可以直接分发编译产物。这个时候用户是无法看到模块对应的源代码的,但是要注意分发的时候要将模块的依赖一起分发,防止在运行时找不到依赖。
总结
Cython 是一种强大的工具,不仅可以提高 Python 代码的性能,还能保护我们代码的知识产权。Cython 编译后的产物可以明显增加逆向工程的难度,保护我们的代码不被盗用。如果我们的需求仅仅只是保护代码,不需要许可证机制并且不需要特别强大的加密的话,可以优先使用 Cython,兼容性和性能会比 Pyarmor 更好一些。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。