nuitka¶
nuitka是一个将Python程序转换为C++的工具。可以用于Python加密。
github: | https://github.com/Nuitka/Nuitka |
---|
安装¶
pip install nuitka
使用方法¶
假设有一个文件 main.py
import sys
def divide(a, b):
return a/b
one = int(sys.argv[1])
two = int(sys.argv[2])
ret = divide(one, two)
print(ret)
加密一个Python程序
python -m nuitka --follow-imports main.py
这种形式,会转换 main.py 以及其依赖的库,比如上面就引用了
sys
。运行完成后,会在当前目录下生成两个文件:
- main.build: 转换、编译生成的临时文件。
- main.exe: 转换后的程序。
此时 main.exe 仍然要依赖 Python 环境才能执行。 如果想要编译一个不依赖于任何外部程序的独立可执行程序。 可以使用
--standalone
选项
编译为完整的可执行程序
添加
--standalone
选项
python -m nuitka --standalone --follow-imports main.py
运行完成后,会在当前目录下生成两个文件夹:
- main.build: 转换、编译生成的临时文件。
- main.dist: 编译完成的C++程序以及其所有依赖.
在windows平台使用
使用方法和Linux一样,但是第一次使用
--standalone
选项时,会提示需要下载一个dependencywalker。http://dependencywalker.com/depends22_x64.zip
输入
Y
, 会自动联网下载, 如果不能联网,可以手动下载这个文件放到C:\Users\viruser.v-desktop\AppData\Local\Nuitka\Nuitka\x86_64
。windows平台一般使用 visual studio, 或者 mingw/MSYS(移植到windows平台的一个linux环境)。 一般来说,Nuitka会自动搜索编译工具并选择一个,如果同时存在 visual studio 和 mingw, 也可以使用
--mingw64
强制使用mingw编译器。
python -m nuitka --standalone --mingw64 main.py
将Python实现的库编译,供其他python程序调用
使用
--module
选项python -m nuitka --module myfunc.py会生成以下文件:
- myfunc.build: 生成的临时文件,没什么用
- myfunc.pyd、myfunc.pyi: 生成的python包,其中myfunc.pyi可以删除, 里面可能包含myfunc的函数声明、源码,用于辅助调试。
myfunc.pyd 本质上是一个动态链接库,也是一个python包,可以直接在其他python脚本中
import myfunc
来使用。
原理¶
Nuitka的原理和 cython
一样, https://cython.org/
因为Python主流实现是用C编写的CPython,可以很方便的和C、C++交互。 比如Python直接调用C,或者在C里面直接写一串Python代码传给Python解释器的执行接口去执行。
Python本身也暴露了一系列C接口供C程序调用。
所以,可以直接将Python代码翻译为相应的C接口调用,这种转换是等价的。
Python代码案例:
t = (1, 2, "three")
转换为C接口调用:
PyObject *t;
t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyLong_FromLong(1L));
PyTuple_SetItem(t, 1, PyLong_FromLong(2L));
PyTuple_SetItem(t, 2, PyUnicode_FromString("three"));
Nuitka的原理就是使用 Python AST 解析Python语法树,并将其翻译为这类C接口,达到转换为C程序的目的。 这种方式兼容性很好,因为本质上还是使用Python方式运行,内部已经看不到任何Python代码,可以实现加密。 但是性能上并不会有显著提升。而且加密后的程序无法调试,因为没有代码,也就丢失了堆栈的大部分信息。
关于性能: 一般来说,性能会有一些提升,大约30%,而且Nuitka在转换为C代码的时候,据说会进行一些优化。