在 Python 应用加密与发布场景中,PyArmor 是一个非常实用的工具。它可以把 Python 脚本转换成难以反向工程的形式,同时提供运行时判断、授权许可等机制,非常适合用于保护商业逻辑。

本文将结合实践经验和官方行为说明,步骤化地讲解如何:

📌 在源机器加密 Python 项目
📌 确保加密后可以复制到其他机器并运行
📌 避免常见错误与坑
📌 配置与运行依赖环境

一、注意 Python 版本

当你在一台机器上加密了你的项目,然后把加密后的 dist 文件夹复制到另一台机器运行时,很容易遇到类似这样的错误:

首先需要在全局使用python 3.10.11版本,在源机器加密之后,如果想要copy 加密后的项目到另一个机器上运行,必须要保证另一台机器运行时使用的也是相同的python版本,否则会报错:

(.venv) PS C:\Users\Admin003\Desktop\dist> C:\Users\Admin003\AppData\Local\Programs\Python\Python310\python app_realtime.py
Traceback (most recent call last):
  File "C:\Users\Admin003\Desktop\dist\app_realtime.py", line 2, in <module>
    from pyarmor_runtime_000000 import __pyarmor__
  File "C:\Users\Admin003\Desktop\dist\pyarmor_runtime_000000\__init__.py", line 2, in <module>
    from .pyarmor_runtime import __pyarmor__
ImportError: DLL load failed while importing pyarmor_runtime: The specified module could not be found.

这是因为 PyArmor 的运行时模块(pyarmor_runtime.pyd 等二进制扩展)依赖于特定版本的 Python 解释器和平台架构。它并不是一个纯 Python 文件,而是与 Python 内部 ABI 紧密绑定的二进制扩展。因此:

✔ 加密运行时一定要用 Python 3.10.11
✔ 目标机器也必须用 Python 3.10.11(且位数相同,如 x64)运行
✘ 否则就会出现 DLL 加载失败或 Marshal 序列化错误等异常
这是 PyArmor 官方文档明确指出的行为,因为运行时扩展包含平台和 Python 版本特定的信息,而不能跨版本运行。

换句话说:目标机器运行环境要与源机器尽可能一致,特别是Python版本,否则即使代码存在,动态库运行也会失败。

二、安装 PyArmor 与注意事项

在源机器上安装 PyArmor:

pip install pyarmor 

这里安装的是 PyArmor 的免费版本。它对于小项目足够使用,但在加密大文件夹时可能会遇到如:out of license这类错误。这是因为试用版对一些复杂/大的目录结构有功能限制。

三、生成加密结果(指定 Python 版本)

在项目根目录执行:

& "C:\Users\Hasee\AppData\Roaming\Python\Python310\Scripts\pyarmor.exe" generate --output dist .

这是推荐的命令形式,它指定了使用特定 Python 环境下的 pyarmor 工具,并且给出了输出目录。

执行结果会在当前目录下生成一个完整的 dist 目录,其中包含:

📌 加密后的脚本(*.py)
📌 支持运行的辅助文件与运行时扩展(runtime package)
📌 许可文件(license.lic
📌 授权密钥文件(pytransform.key

四、复制pytransform.py文件到 dist

pytransform.py 是 PyArmor 运行时的核心文件之一,必须放入 dist 目录。

Copy-Item -Force "C:\Users\Hasee\AppData\Roaming\Python\Python310\site-packages\pyarmor\pytransform.py" -Destination ".\dist\pytransform.py"

为什么需要它,设计到PyArmor 使用分层的运行时架构:

  • pyarmor_runtime.pyd :底层 DLL 负责核心解密逻辑

  • pytransform.py :上层 Python 接口,提供易用的 API

  • pyarmor_runtime_000000/__init__.py :初始化入口

这三个文件配合工作,才能确保加密后的代码在目标机器上正常运行。

如果不放入:

  • 加密后的程序会抛出 ModuleNotFoundError: No module named 'pytransform' 或类似错误

  • 无法正确加载和执行加密的 Python 模块

  • 程序无法正常运行

五、dist 目录结构

最终的目录可能看起来像这样:

dist/
├── app_realtime.py
├── other_encrypted_scripts.py
├── pytransform.py
├── pytransform.key      ← 可选:项目密钥文件
├── license.lic          ← 可选:运行时许可证文件
└── pyarmor_runtime_000000/
    ├── __init__.py
    └── pyarmor_runtime.pyd  ← 加密运行时动态库

文件

必需

作用

pytransform.py

运行时 Python 接口,负责加载动态库等

pyarmor_runtime_000000/pyarmor_runtime.pyd

核心运行时动态库,负责解密执行逻辑

pytransform.key

⚠ 有条件

项目专用密钥(可选,看用途)

license.lic

⚠ 有条件

授权许可证(可选,控制授权行为)

加密后的脚本

项目代码本体的加密版本

5.1 pytransform.key:什么是它?什么时候需要?

5.1.1 作用

pytransform.key项目级别的密钥文件,用于让运行时动态库和加密脚本一致:它包含了用于对字节码加密/解密的信息。
这是 PyArmor 生成的本地(项目)密钥,而不是全局的默认密钥。

5.1.2 全局密钥 vs 项目密钥

PyArmor 有两种密钥来源:

全局密钥箱(~/.pyarmor/.pyarmor_capsule.zip):这是默认的“密钥仓库”,如果你没有显式生成项目密钥,那么 PyArmor 使用的就是它里面的密钥进行加密。

项目密钥文件(pytransform.key):当你明确为某个项目生成专用密钥时,会得到这个文件。生成这个文件后,把它加到 dist 里可以让此 dist 包拥有自己的“独立密钥”,不再依赖全局密钥箱。

5.1.3 为什么没放它也能运行?

这是因为:如果没有本地的 pytransform.key,PyArmor 运行时 会回退去使用全局密钥箱中的密钥 来解密和执行代码。

运行时的查找顺序是:

  1. 当前目录下的 license.licpytransform.key

  2. pytransform.py 所在目录里的这两个文件

  3. 动态库内内嵌的默认许可/密钥

因此只要能找到可用的密钥和动态库,脚本是可以正常执行的。

5.1.4 什么时候才需要 pytransform.key

建议显式生成和使用 pytransform.key 的场景:

  • 为同一项目重复加密多个版本,确保版本之间密钥一致

  • 多个客户需要不同授权许可 时,需要基于相同 project key 生成不同 license 文件

  • 想离线管理每个项目的密钥,便于长期维护和控制

5.1.5 如何显式生成项目密钥文件?

用下面命令生成项目专用密钥:

pyarmor gen key --output keys

该命令会在当前目录的 keys/ 下生成一个 pytransform.key
之后你可以复制到 dist:

Copy-Item keys\pytransform.key dist\

这样 dist 就带上了你自己项目的密钥,而不是依赖全局密钥箱。

5.2 license.lic:什么是它?什么时候需要它?

5.2.1 默认 license.lic 的作用

当你用 PyArmor 标准命令加密时,加密引擎会生成一个默认的 license.lic 放在 dist(以前版本是单独文件,现在一些版本甚至把它嵌入到了动态库里)。

这个默认 license.lic

✔ 表示“允许加密脚本在任何机器上全部运行”
✔ 没有过期时间、没有设备绑定
✔ 是最宽松的许可

根据官方文档,在新版 PyArmor 中默认许可信息已经可以被嵌入动态库,因此 即使没有单独 license.lic 文件,脚本仍能运行

5.2.2 自定义 license.lic 的意义

如果你希望对发布版做授权控制,则需要生成自定义的 license.lic

🔸 设置使用期限(过期时间)
🔸 绑定特定机器(MAC、硬盘序列号)运行
🔸 限制只能在指定环境运行

这时就不能使用默认的“无限制许可证”,必须给客户一个单独的 license.lic

5.1.3 如何生成自定义许可证?

PyArmor 提供命令来生成不同策略的许可证文件:

✨ 生成带过期时间的许可证

pyarmor licenses --expired 2025-12-31 myproj

执行后,会在类似:

licenses/myproj/license.lic

路径下生成一个新的许可证文件,可以拷贝到 dist:

Copy-Item licenses\myproj\license.lic dist\

✨ 生成绑定机器的许可证

pyarmor licenses --bind-disk "硬盘序列号" --bind-mac "MAC地址" myprojb

这个许可证只允许在该硬盘和该 MAC 的机器上运行。

官方文档说明:

加密后的脚本在运行时会先尝试在当前路径查找 license.licpytransform.key
如果找不到,再去 pytransform.py 所在目录查找。
最后,如果没有这些文件也没有错误,那么运行时可能使用动态库内嵌的默认许可。

六、放入.env配置文件

将环境配置放入到dist目录,但是不能放入任何敏感信息,因为一旦运行时,所有的变量都是可获取的明文

七、安装项目依赖并运行

加密后的项目通常仍然需要依赖其他库(比如 Flask、aiohttp、mmpose 等),因此你需要在目标机器上:

创建虚拟环境:

python -m venv .venv

激活虚拟环境:

C:\Code\Navtalk\Services\MuseTalk\.venv\Scripts\Activate.ps1

安装依赖等等。

运行目标 Python 脚本:


python app_realtime.py

这时:

✔ Python 会先加载 PyArmor 运行时扩展
✔ 再执行加密后的脚本逻辑
✔ 你得到与未加密版本相同的运行效果