前言:对python项目进行加密设置,实现 日期 + ip 的 licence 加密
一、pyarmor 介绍
PyArmor 是一款商业 Python 代码加密工具,可通过字节码转换、机器码编译等技术保护 Python 代码不被逆向工程。它主要用于保护商业软件、算法知识产权或敏感代码逻辑,防止未授权访问、修改或复制。
核心功能
- 代码加密
转换 Python 字节码为混淆格式,生成加密脚本。
支持直接运行加密代码,无需额外解密步骤。 - 多平台支持
兼容 Windows、Linux、macOS 等主流操作系统。
支持 x86、ARM 等多种硬件架构。 - 运行时保护
检测调试器、反编译工具,防止动态分析。
限制程序在特定机器、时间或环境中运行。 - 灵活部署
可选择性加密部分模块,保留纯 Python 代码兼容性。
支持加密 Python 包(Package)和应用程序。
二、单脚步加密
2.1 日期加密
2.1.1 单次设置加密方式
(1)安装包
bash
pip install pyarmor
(2)创建测试脚本
hello.py脚本
python
for i in range(10):
print(i, 'run success')
(3)执行日期加密命令
bash
pyarmor gen -e "2025-07-02T17:20:00" hello.py
- -e : 有效期日期,我这里设置的是运行时的20分钟之内(也可以直接填入整数,单位为天)
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>pyarmor gen -e "2025-07-02T17:20:00" hello.py
INFO Python 3.10.0
INFO Pyarmor 9.1.7 (trial), 000000, non-profits
INFO Platform windows.x86_64
INFO search inputs ...
INFO find script hello.py
INFO find 1 top resources
INFO start to generate runtime files
INFO target platforms {'windows.amd64'}
INFO write dist\pyarmor_runtime_000000\pyarmor_runtime.pyd
INFO generate runtime files OK
INFO start to obfuscate scripts
INFO process resource "hello"
INFO obfuscating file hello.py
INFO write dist\hello.py
INFO obfuscate scripts OK

(4)运行加密后的文件
bash
python dist/hello.py
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>python dist/hello.py
0 run success
1 run success
2 run success
3 run success
4 run success
5 run success
6 run success
7 run success
8 run success
9 run success
(5)日期时间过了之后运行结果
bash
python dist/hello.py
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>python dist/hello.py
Traceback (most recent call last):
File "E:\zhx\workspace_2025\DaBao\module_Read\dist\hello.py", line 2, in <module>
from pyarmor_runtime_000000 import __pyarmor__
File "E:\zhx\workspace_2025\DaBao\module_Read\dist\pyarmor_runtime_000000\__init__.py", line 2, in <module>
from .pyarmor_runtime import __pyarmor__
RuntimeError: this license key is expired (1:11086)
提醒 licence 过期了
2.1.2 使用外部文件存放运行密钥
(1)在加密脚本的时候指定使用外部密钥
bash
pyarmor gen --outer hello.py
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>pyarmor gen --outer hello.py
INFO Python 3.10.0
INFO Pyarmor 9.1.7 (trial), 000000, non-profits
INFO Platform windows.x86_64
INFO search inputs ...
INFO find script hello.py
INFO find 1 top resources
INFO start to generate runtime files
INFO target platforms {'windows.amd64'}
INFO write dist\pyarmor_runtime_000000\pyarmor_runtime.pyd
INFO generate runtime files OK
INFO start to obfuscate scripts
INFO process resource "hello"
INFO obfuscating file hello.py
INFO write dist\hello.py
INFO obfuscate scripts OK
(2)运行加密的文件
bash
python dist/hello.py
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>python dist/hello.py
Traceback (most recent call last):
File "E:\zhx\workspace_2025\DaBao\module_Read\dist\hello.py", line 2, in <module>
from pyarmor_runtime_000000 import __pyarmor__
File "E:\zhx\workspace_2025\DaBao\module_Read\dist\pyarmor_runtime_000000\__init__.py", line 2, in <module>
from .pyarmor_runtime import __pyarmor__
RuntimeError: missing license key to run the script (1:10672)
提醒 licence 不存在
(3)生成 licence
bash
pyarmor gen key -O dist/key111 -e 1
- -e 设置为 1 天
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>pyarmor gen key -O dist/key111 -e 1
INFO Python 3.10.0
INFO Pyarmor 9.1.7 (trial), 000000, non-profits
INFO Platform windows.x86_64
INFO start to generate outer runtime key "pyarmor.rkey"
INFO write dist/key111\pyarmor.rkey
INFO generate outer runtime key OK
将 dist/key111//pyarmor.rkey 下的licence 拷贝到 hello的加密文件dist/pyarmor_runtime_000000/ 下
bash
cp dist/key2/pyarmor.rkey dist/pyarmor_runtime_000000/
(4)运行查看
bash
(smart_campus) E:\zhx\workspace_2025\DaBao\module_Read>python dist/hello.py
0 run success
1 run success
2 run success
3 run success
4 run success
5 run success
6 run success
7 run success
8 run success
9 run success
正常可以运行了
2.2 周期性检查运行密钥
当运行加密的服务时一直处于运行的状态时,需要设置周期性检查命令。
使用下面的命令生成的加密脚本,运行的时候会每隔一个小时对运行密钥进行一次检查
bash
pyarmor gen --period 1 hello.py
2.3 日期+设备ip 加密
使用下面的命令绑定加密脚本到多台设备:
bash
pyarmor gen -e 1 -b "fe80::6172:250a:329d:3f97" -b "f48:tf:f2:j7:70:2f" hello.py
- -b :物理地址 / ip / ipv4地址
- -e :日期
注意: 当我使用linux上的mac地址时是没有问题的,但是当我使用windows的物理地址是会报 "ERROR invalid device info "9C-***-44" " ,这个时候我们只需要把windows物理地址中的 '-' 改成 ':' 就行了。
测试:当在其他设备上运行时
bash
Traceback (most recent call last):
File "/home/ws/store/zhx/workspace_2024/dist/dd.py", line 2, in <module>
from pyarmor_runtime_000000 import __pyarmor__
File "/home/ws/store/zhx/workspace_2024/dist/pyarmor_runtime_000000/__init__.py", line 2, in <module>
from .pyarmor_runtime import __pyarmor__
RuntimeError: 脚本许可证不可用于当前设备 (1:10252)
三、python项目加密
3.1 使用单次加密方式
3.1.1 查看待打包的python项目目录

- serverMain.py 为启动脚本,启动成功如下:
3.1.2 命令介绍
- -r :递归搜索目录下面的 Python 脚本,否则只搜索当前目录下面的脚本
- -i :保存运行辅助文件到加密包的内部。
- -O :设置加密脚本的输出路径,默认值是 dist
3.1.3 分析
(1)在脚本互相引用的时候,需要把路径写全,如下在serverMain.py中引用:
python
from module_Read.Router_Read import RouterRead
(2) 如果使用直接对整个项目进行加密时
bash
pyarmor gen -e 1 -r -i DaBao
运行加密后的文件会报错1
bash
(smart_campus) E:\zhx\workspace_2025>python dist/DaBao/serverMain.py
Traceback (most recent call last):
File "E:\zhx\workspace_2025\dist\DaBao\serverMain.py", line 2, in <module>
from .pyarmor_runtime_000000 import __pyarmor__
ImportError: attempted relative import with no known parent package
报错2
bash
(smart_campus) E:\zhx\workspace_2025>python -m dist.DaBao.serverMain
Traceback (most recent call last):
File "F:\anaconda3\envs\smart_campus\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "F:\anaconda3\envs\smart_campus\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "<frozen __main__>", line 3, in <module>
File "<frozen DaBao.serverMain>", line 11, in <module>
ModuleNotFoundError: No module named 'module_Read'
3.1.4 正确的加密方式
因为我们的所有代码是在DaBao下,对应的在dist/下包含DaBao下所有的代码,为了名称统一,使用 -O 输出路径把dist改成DaBao。
然后对应DaBao中的代码,有configs、module_Logging、module_Read、tet4个文件夹,一个serverMain.py 脚本,所有我们需要区分开加密,文件夹的需要使用 "-r -i" 这 两个参数,对应 "serverMain.py" 则不需要。
注: 每个文件夹(不管几层,每层都需要)下都必须包含"init.py" 脚本 ,确保每个文件夹都被加载
(1)文件夹加密(需要保存为DaBao的话使用-O参数,这里使用默认的dist)
bash
pyarmor gen -e 1 -r -i module_Read configs module_Logging tet
bash
(smart_campus) E:\zhx\workspace_2025\DaBao>pyarmor gen -e 1 -r -i module_Read configs module_Logging tet
INFO Python 3.10.0
INFO Pyarmor 9.1.7 (trial), 000000, non-profits
INFO Platform windows.x86_64
INFO search inputs ...
INFO find package at module_Read
INFO find package at configs
INFO find package at module_Logging
INFO find package at tet
INFO find 4 top resources
INFO start to generate runtime files
INFO target platforms {'windows.amd64'}
INFO write dist\module_Read\pyarmor_runtime_000000\pyarmor_runtime.pyd
INFO generate runtime files OK
INFO start to obfuscate scripts
INFO process resource "module_Read"
INFO obfuscating file readExcel.py
INFO write dist\module_Read\readExcel.py
INFO obfuscating file read_document.py
INFO write dist\module_Read\read_document.py
INFO obfuscating file read_excel.py
INFO write dist\module_Read\read_excel.py
INFO obfuscating file Router_Read.py
INFO write dist\module_Read\Router_Read.py
INFO obfuscating file toolRead.py
INFO write dist\module_Read\toolRead.py
INFO obfuscating file __init__.py
INFO write dist\module_Read\__init__.py
INFO obfuscating file __init__.py
INFO write dist\module_Read\data\__init__.py
INFO obfuscating file __init__.py
INFO write dist\module_Read\static\__init__.py
INFO obfuscating file __init__.py
INFO write dist\module_Read\static\111\__init__.py
INFO obfuscating file __init__.py
INFO write dist\module_Read\static\documents\__init__.py
INFO obfuscating file __init__.py
INFO write dist\module_Read\static\file_img\__init__.py
INFO process resource "configs"
INFO obfuscating file config.py
INFO write dist\configs\config.py
INFO obfuscating file __init__.py
INFO write dist\configs\__init__.py
INFO process resource "module_Logging"
INFO obfuscating file loggingD1.py
INFO write dist\module_Logging\loggingD1.py
INFO obfuscating file __init__.py
INFO write dist\module_Logging\__init__.py
INFO process resource "tet"
INFO obfuscating file dd.py
INFO write dist\tet\dd.py
INFO obfuscating file hello.py
INFO write dist\tet\hello.py
INFO obfuscating file hh.py
INFO write dist\tet\hh.py
INFO obfuscating file __init__.py
INFO write dist\tet\__init__.py
INFO obfuscate scripts OK
(2)脚本加密
bash
pyarmor gen -e 1 serverMain.py
bash
(smart_campus) E:\zhx\workspace_2025\DaBao>pyarmor gen -e 1 serverMain.py
INFO Python 3.10.0
INFO Pyarmor 9.1.7 (trial), 000000, non-profits
INFO Platform windows.x86_64
INFO search inputs ...
INFO find script serverMain.py
INFO find 1 top resources
INFO start to generate runtime files
INFO target platforms {'windows.amd64'}
INFO write dist\pyarmor_runtime_000000\pyarmor_runtime.pyd
INFO generate runtime files OK
INFO start to obfuscate scripts
INFO process resource "serverMain"
INFO obfuscating file serverMain.py
INFO write dist\serverMain.py
INFO obfuscate scripts OK

3.1.5 运行加密文件
bash
python dist/serverMain.py
bash
(smart_campus) E:\zhx\workspace_2025\DaBao>python dist/serverMain.py
INFO: Uvicorn running on http://0.0.0.0:8208 (Press CTRL+C to quit)
INFO: Started parent process [36260]
INFO: Started server process [36624]
INFO: Waiting for application startup.
INFO: Started server process [34520]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Application startup complete.

调用接口测试
3.2 使用外部文件存放运行密钥
3.2.1 外部加密
bash
pyarmor gen --outer -r -i configs module_Logging module_Read tet serverMain.py
pyarmor gen --outer serverMain.py
运行测试报不存在licence
bash
(smart_campus) E:\zhx\workspace_2025\DaBao>python dist/serverMain.py
Traceback (most recent call last):
File "E:\zhx\workspace_2025\DaBao\dist\serverMain.py", line 2, in <module>
from pyarmor_runtime_000000 import __pyarmor__
File "E:\zhx\workspace_2025\DaBao\dist\pyarmor_runtime_000000\__init__.py", line 2, in <module>
from .pyarmor_runtime import __pyarmor__
RuntimeError: missing license key to run the script (1:10672)
3.2.2 生成licence
时效为5分钟之内
bash
pyarmor gen key -O key222 -e "2025-07-03T11:55:00"
将这个licence粘贴到每个 pyarmor_runtime_000000 下
运行看结果
等5分钟后运行看结果
已经提醒licence过期了
3.2.3 周期性检查
由于当前代码运行之后是一个服务,只要启动的时候licence没有过期则可以一直运行着,可以使用 --period 参数对正在运行的服务进行周期性的检查
bash
pyarmor gen key --period 1 -O key222 -e "2025-07-03T12:30:00"
然后把服务起来,1小时之后会进行自动检查
bash
(smart_campus) E:\zhx\workspace_2025\DaBao>python dist/serverMain.py
INFO: Uvicorn running on http://0.0.0.0:8208 (Press CTRL+C to quit)
INFO: Started parent process [34736]
INFO: Started server process [8884]
INFO: Started server process [15508]
INFO: Waiting for application startup.
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Application startup complete.

一个小时后重新调用
bash
INFO: 192.168.1.155:52219 - "POST /Reader/DocumentReader HTTP/1.1" 200 OK
INFO: 192.168.1.155:63661 - "POST /Reader/DocumentReader HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "F:\anaconda3\envs\smart_campus\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 403, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "F:\anaconda3\envs\smart_campus\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
return await self.app(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\fastapi\applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
raise exc
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
await self.app(scope, receive, _send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\middleware\exceptions.py", line 62, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
raise exc
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\routing.py", line 715, in __call__
await self.middleware_stack(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\routing.py", line 735, in app
await route.handle(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\routing.py", line 288, in handle
await self.app(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\routing.py", line 76, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
raise exc
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\starlette\routing.py", line 73, in app
response = await f(request)
File "F:\anaconda3\envs\smart_campus\lib\site-packages\fastapi\routing.py", line 301, in app
raw_response = await run_endpoint_function(
File "F:\anaconda3\envs\smart_campus\lib\site-packages\fastapi\routing.py", line 212, in run_endpoint_function
return await dependant.call(**values)
File "<frozen module_Read.Router_Read>", line 23, in DocumentReader
RuntimeError: this license key is expired (1:11086)
看到提醒licence过期了。
四、绑定平台
- --platform
用于跨平台加密脚本指定运行加密脚本的目标平台
这个选项可以使用多次,也可以使用逗号把多个平台名称分开
平台名称必须是 Pyarmor 定义的 运行平台 名称
- Windows
- windows.x86_64
- windows.x86
- Many Linuxs
- linux.x86_64
- linux.x86
- linux.aarch64
- linux.armv7
- Apple Intel and Silicon
- darwin.x86_64
- darwin.aarch64 or darwin.arm64
- FreeBSD
- freebsd.x86_64
- Alpine Linux (musl-c)
- alpine.x86_64
- alpine.aarch64
- Android
- android.x86_64
- android.x86
- android.aarch64
- android.armv7