python代码编译总结-用于代码加密
基于一个自废武功式的决定,服务需要做成标准件在客户服务器上运行,因此调研了python代码加密的相关内容。py的代码混淆没有被采用,而是采用cython编译成二进制文件进而掩盖源码的方式对代码加密。
准备工作:
1.安装cython ,pip install cython
2.Linux上安装gcc ,Win需要准备vc的环境,建议安装vs2019以上,自带部分vc环境
setup脚本,请根据需要自行添加module_list:
from distutils.core import setup from Cython.Build import cythonize import setuptools from distutils.extension import Extension setup(ext_modules=cythonize(module_list = [Extension('server', ['server.py'])]))
module_list 中的Extension,每个文件根据路径和名称确定模块名。__init__.py不建议编译,因为模块名跟文件一一对应,将模块名指定为文件夹名称编译后运行时会找不到模块。可以使用os.walk()来遍历,批量处理文件路径和模块名称。
Setup脚本使用当前的开发环境,终端命令如下:python setup.py build_ext --inplace
build_ext 会创建build文件夹产生编译中间产物 --inplace 最终的编译结果(如.so文件)生成在原路径下。linux下会生成so文件,win下生成的是pyd文件,都是二进制文件,原调用方式不变。
目录结构如下图:
完整的setup.py代码如下:
from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize import os filelist = [] ex_list = [] for r, d, f in os.walk('onmt'): if '__' in r: continue if 'templates' in r: continue # 不需要加密的文件夹 for ff in f: if ff.endswith('.c') or ff.endswith('.so'): os.remove(os.path.join(r, ff)) continue if '__' in ff: continue filelist.append(os.path.join(r, ff)) if __name__ == '__main__': for f in filelist: if '__' in f: continue # 不可以将__init__.py文件放入待加密列表 else: ex_list.append(Extension(f.split('.py')[0].replace('/', '.'), [f])) # 详见说明1 # ex_list.append(Extension(f.split('.py')[0].replace('/', '.').split('.')[-1], [f])) # 详见说明2 setup(ext_modules=cythonize(ex_list, compiler_directives={'language_level': 3}
)) for f in filelist: os.remove(f) #删除源文件来验证编译是否成功,请一定要提前备份好代码
说明:
- 将源文件路径中/转换为. 编译后再次读取时模块可能会出现找不到的情况。
以onmt/bin/ server.py文件为例,此行代码执行的编译结果中.c临时文件里的模块名字为onmt.bin.server。注意此时so文件与原py文件在同一路径下。此时在server_run中使用onmt.bin.server引用so文件时可能会出错,so文件可能被python识别为onmt.bin.server.onmt.bin.server,导致模块找不到。
2. 模块名称与文件名一致,不再包含原文件路径。
以onmt/bin/server.py文件为例,此行代码执行的编译结果中.c临时文件里的模块名字是server。注意此时so文件与setup.py在同一路径下,需要人为将so文件移动到原文件对应路径下。此时在server_run中使用onmt.bin.server引用so文件也有无法找到模块的可能。
鉴于以上两种情况皆有成功和失败的情况出现,较为稳妥的办法是使用原虚拟环境进行编译,在确认编译后so文件可以使用的情况下,导出原虚拟环境与编译后so文件一起使用。
*********************************************************************************************************************************************
参考资料:Python 2.7 cython cythonize py 编译成 pyd 谈谈那些坑 - ibingshan - 博客园 (cnblogs.com)