3. 使用教程
在本教程中,均以下面的目录结构为例来进行说明:
project/src/
├── foo.py
├── fibo.py
├── jsontool.py
└── tomjson/
├── __init__.py
├── encoder.py
├── decoder.py
└── scanner.py
如果没有特别说明,本教程中默认的目录都是:
$ cd project/src/
示例脚本的下载地址
3.1. 安装和注册 Pyarmor
Pyarmor 发布在 PyPI 上面,使用下面的命令直接安装:
$ pip install pyarmor.cli
重构功能需要购买相应的许可证并进行注册
3.2. 生成重构型脚本
下面我们来说明如何重构一个简单脚本 foo.py
首先为其创建一个工程,工程只包含一个脚本 foo.py:
$ pyarmor init -e foo.py
然后构建工程,指定输出类型为重构型脚本:
$ pyarmor build --rst
默认输出是在 dist ,查看输出脚本:
$ cat dist/foo.py
运行重构后的脚本:
$ python dist/foo.py
重构脚本只是对函数,参数,变量以及类,方法,属性进行了重命名,所以使用方式和原来的脚本一样
3.3. 重构复杂脚本
默认选项可以重构简单脚本,对于复杂脚本,重构之后脚本可能无法正确运行。
例如,我们重新创建一个包含复杂脚本 fibo.py 的新工程:
$ pyarmor init --clean -e fibo.py
当使用下面的命令生成重构型脚本的时候,最后会出现如下警告:
$ pyarmor build --rft
...
WARNING There are variables of unknown type
WARNING There are function calls which may use unknown arguments
...
运行重构脚本会报错:
$ python dist/fibo.py
AttributeError: 'pyarmor__7' object has no attribute 'run'
这时候可以使用下面的命令自动生成额外的重构规则:
$ pyarmor build --autofix 1
然后再次执行重构命令:
$ pyarmor build --rst
运行重构后的脚本:
$ python dist/fibo.py
使用上面的方法生成的重构规则会保留所有未知的属性,也就是说,如果不能确定某一个属性是否需要重命名,那么所有脚本中和该属性重名的名称都保留不变
如果需要重命名所有类方法和属性,可以清除上面生成的规则:
$ pyarmor build --autofix 0
然后根据需要人工配置重构规则,但是这需要学习和了解重构规则的使用方法,详细内容请参考后面高级重构功能
3.4. 生成迷你型脚本
生成迷你型加密脚本需要首先安装包 pyarmor.mini:
$ pip install pyarmor.mini
我们依旧使用上例中创建的工程,使用相同配置生成迷你型脚本:
$ pyarmor build --mini
查看加密脚本:
$ cat dist/fibo.py
运行加密之后的脚本:
$ python dist/fibo.py
迷你型脚本的不可逆程度基本和 .pyc 文件相当,所以一般会首先对脚本进行重构,增加其不可逆程度,然后在生成迷你型脚本。使用下面的命令可以直接生成迷你型重构脚本:
$ pyarmor build --mini-rft
一般情况下,首先单独生成重构型脚本进行调试,调试通过之后直接使用相同配置生成迷你型脚本
3.5. 发布迷你型脚本
发布迷你型脚本需要把依赖包 pyarmor.mini 加入到发布包中
或者在运行环境直接安装依赖包:
$ pip install pyarmor.mini
不是所有的平台都支持 pyarmor.mini,目前仅支持五个平台
linux.x86_64, darwin.x86_64, windows.x86_64
linux.aarch64, darwin.arm64
3.5.1. 支持 Freethreading
迷你型脚本支持 Freethreading (Python 3.13+) 特性
在支持 Freethreading 的 Python 环境,使用 pip >=24.1 安装依赖包 pyarmor.mini ,这样安装的就是支持 Freethreading 的扩展模块 pyarmor_minit , 扩展模块的名称包含后缀 t ,支持 Freethreading 的 wheel 标签为 cp313t
3.6. 重构包
下面说明如何重构包 tomjson
首先创建一个工程,包含包 tomjson:
$ pyarmor init --clean -p tomjson
因为外部模块需要导入包中的类和函数,所以这些输出的名称不能进行重命名
这就需要启用自动输出选项 export_mode:
$ pyarmor env -p set rft:export_mode 1
这样的话,模块属性 __all__
中列出的名称不会被重命名
如果该名称是一个类,那么类的属性和方法,都不会进行重命名
如果该名称是一个函数,那么函数的参数也不会进行重命名
然后重构整个包:
$ pyarmor build --rft
也可以根据需要生成迷你型加密包:
$ pyarmor build --mini-rft
发布迷你型加密包需要把包 pyarmor.mini 作为依赖先进行安装
3.7. 创建复杂工程
下面我们来创建一个工程,包含当前目录下面的脚本 jsontool.py 以及内部包 tomjson,但是不包含 fibo.py 和 venv 目录:
$ pyarmor init --clean --src . -r --exclude fibo.py --exclude venv
该命令会自动搜索 --src
下面的文件和目录,把发现的模块和包自动增加到工程中
查看工程包含的所有项目:
$ pyarmor build --list
重构整个工程:
$ pyarmor build --rft
运行一下重构后的脚本:
$ python dist/jsontool.py
3.8. 高级重构功能
对于复杂脚本,使用默认选项生成的重构型脚本,运行的时候主要会出现两种类型的问题
对象的属性名称不存在
函数的参数名称不存在
例如:
AttributeError: 'pyarmor__7' object has no attribute 'run'
除了上文中提到的自动生成重构规则的方法之外,还可以通过人工配置规则的方式来解决
3.8.1. 属性名称不存在
如果提示属性名称 xxxx
不存在,最简单的方式是直接增加排除规则,不重命名该属性:
$ pyarmor env -p set rft:exclude_names xxxx
这样可以简化配置,但是可能造成更多的名称没有被重命名
另外一种方式,是对出现问题的属性进行单独配置
例如在脚本 fibo.py 中,有如下的代码块:
def fib(obj, n):
obj.name = 'fibo'
obj.value = n
obj.run()
return obj.result
因为参数 obj 的类型不确定,所以默认情况是不会对其属性进行重命名,这样运行的时候会导致问题属性找不到的问题。
一种解决方案是使用 annotation 指定变量类型,例如:
def fib(obj: QuickFibo, n):
obj.name = 'fibo'
obj.value = n
obj.run()
return obj.result
另外一种解决方案是不修改脚本,使用规则指定需要修改的属性。例如,下面的规则指定模块 fibo 中的函数 fib 中变量 obj 的所有属性都进行重命名:
$ pyarmor env -p push rft:attr_rules "fibo::fib:obj.*"
配置新规则之后,需要重新构建工程:
$ pyarmor build --rft
3.8.2. 函数参数名称不存在
如果错误提示是参数名称不存在,那么可以直接禁用重命名参数:
$ pyarmor env -p set rft:argument_mode 0
或者也可以仅重命名 posonly 参数和 vararg 和 kwarg 参数:
$ pyarmor env -p set rft:argument_mode 1
这样可以简化配置,但是大部分参数可能没有被重命名
另外一种方式是仅仅禁用某一个函数重命名参数,例如在脚本 fibo.py 中,有如下的代码块:
def show(rlist, n, delta=2):
print('fibo', n, 'is', rlist)
return n + delta
if __name__ == '__main__':
...
kwarg = {'n': n, 'delta': 3}
show(result, **kwarg)
调用函数 show 的时候使用了参数 kwarg ,而字典的键值重构之后不会改变,而函数的参数名称都进行了重命名,所以运行重构后的脚本会导致出现参数不存在错误
使用下面的命令配置函数 show 的参数不能进行重命名:
$ pyarmor env -p set rft:argument_mode 3
$ pyarmor env -p push rft:exclude_funcs fibo::show
配置修改之后,需要重新构建脚本:
$ pyarmor build --rft