使用pyarmor对python项目进行licence加密

前言:对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项目目录


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
相关推荐
LiuYiCheng1234561 分钟前
Python游戏开发:Pygame全面指南与实战
python·pygame
魔障阿Q13 分钟前
华为310P3模型转换及python推理
人工智能·python·深度学习·yolo·计算机视觉·华为
LZQqqqqo37 分钟前
C# 接口(interface 定义接口的关键字)
java·开发语言·c#
寒水馨1 小时前
Java 9 新特性解析
java·开发语言·新特性·java9·jdk9
都叫我大帅哥1 小时前
决策树:从零开始的机器学习“算命大师”修炼手册
python·机器学习
这里有鱼汤1 小时前
首个支持A股的AI多智能体金融系统,来了
前端·python
拓端研究室1 小时前
专题:2025医药生物行业趋势与投融资研究报告|附90+份报告PDF、原数据表汇总下载
android·开发语言·kotlin
云霄IT1 小时前
python使用ffmpeg录制rtmp/m3u8推流视频并按ctrl+c实现优雅退出
python·ffmpeg·音视频
都叫我大帅哥1 小时前
我给大模型装上“记忆黄金券”:LangChain的ConversationSummaryBufferMemory全解析
python·langchain·ai编程