- 开发工具
- 应用安全
【免费下载链接】pyarmor
A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
PyArmor 的 Project(项目)机制把"源目录 + 配置文件 + 输出路径"封装成一个可重复执行的混淆工作单元,让你不再每次手工挑选脚本、重复敲参数,而是通过init、config、build、info四个命令完成从初始化到增量构建的全流程。本文基于仓库文档 docs.7/project.rst 展开,并结合源码 src/project.py、src/pyarmor.py 与 src/cli/project.py 深入讲解项目配置文件中每个属性的含义、默认值与底层行为,读完即可上手用项目方式管理你的混淆脚本。
Project 是什么
Project 是一个包含自身配置文件的文件夹,用于统一管理一批待混淆的 Python 脚本。它的本质是"目录 + 一份 JSON 配置",配置文件默认名为.pyarmor_config(见 src/config.py 中的config_filename = '.pyarmor_config'),存放在项目路径下。
使用 Project 管理混淆脚本有四个显著优势:
- 增量构建:只有自上次构建以来发生变更的脚本才会被重新混淆,无需每次全量处理;
- 过滤脚本:可以在项目中精确筛选待混淆的脚本,排除某些脚本或目录;
- 不同混淆模式:可以为同一批脚本配置并使用不同的混淆模式;
- 管理更便捷:所有脚本的混淆状态与构建记录集中在项目维度统一维护。
从源码角度看,项目对象在 src/project.py 中实现为Project(dict)类,它维护了从version、name到build_time等一系列默认属性,并用build_time记录最后一次构建时间——这正是增量构建判定的依据:get_build_files()会比较每个脚本的mtime与build_time,仅收集更新过的文件(src/project.py)。
注意:本文以 PyArmor 7.x 的经典 Project 机制为主进行讲解(与 docs.7/project.rst 对应)。在 9.x 的新版 CLI 中,项目信息改由本地配置文件(
[project]节)承载,相关实现见 src/cli/project.py,本文会在相应位置给出对照说明。
创建项目:init 命令
在当前目录创建项目
在源代码目录下执行:
cd examples/pybench pyarmor init --entry=pybench.py这会在当前路径生成项目配置文件.pyarmor_config。源码中_init的实现(src/pyarmor.py)做了如下工作:
- 若目标路径已存在
.pyarmor_config,直接报错A project already exists in "...",防止重复初始化; - 将
--src解析为绝对路径写入配置(未指定时默认为当前目录的绝对路径); - 根据
--type(app/pkg/auto)与入口脚本是否以__init__.py结尾,决定项目是"独立应用"还是"包"(is_package=1); - 以项目目录的 basename 作为
name与title,调用project.save()写出 JSON 配置。
在指定路径创建项目
如果想把项目配置保存在其他位置,可以使用--src显式指定源码路径:
pyarmor init --src=examples/pybench --entry=pybench.py projects/pybench此时会创建projects/pybench目录,并在其中保存.pyarmor_config。注意src与项目路径是相对关系:配置中记录的是从项目文件夹出发的相对路径(当src为相对路径时),这样整个项目目录迁移后配置依然可用。
init还支持以下参数(见 src/pyarmor.py):
| 参数 | 说明 |
|---|---|
-t, --type | auto(默认)/app/pkg;pkg或 auto 且入口为__init__.py时自动视为包 |
-e, --entry | 项目入口脚本,可多个(逗号分隔) |
-s, --src | 项目源码基准路径,默认为空(当前目录) |
project | 项目路径,默认为空(当前目录) |
项目日常操作:info / build / config
项目的常规用法是"进入项目路径后执行一切操作":
cd projects/pybench查看项目信息:pyarmor info
pyarmor info_info实现(src/pyarmor.py)打开项目配置后调用Project.info(),后者会把全部配置属性(含build_time,格式化为可读时间)逐行输出(src/project.py)。
构建项目:pyarmor build
pyarmor build构建是项目的核心动作,源码中_build的执行流程(src/pyarmor.py)大致如下:
- 打开项目并做一致性检查(
project.check()),包括:项目路径存在、src存在且为绝对路径、src与output不得相同、license 文件合法等(src/project.py); - 通过 manifest 模板在
src下匹配待混淆文件(get_build_files()); - 为每个入口脚本生成运行时文件与引导(bootstrap)代码;
- 逐个脚本加密混淆,输出到
output路径; - 将当前时间写入
build_time并保存配置,作为下次增量构建的基准。
修改项目配置:pyarmor config
pyarmor config --manifest "include *.py, prune dist, prune test"config命令(_config,src/pyarmor.py)用于更新项目配置:读取现有配置 → 将参数归一化(相对路径基于项目路径换算)→ 调用project._update()只更新显式传入的属性 → 保存回.pyarmor_config。
例如,排除dist、test目录中的.py文件:
pyarmor config --manifest "include *.py, prune dist, prune test"manifest 中还可以列出数据文件,构建时会一并拷贝到输出路径:
pyarmor config --manifest "include *.py, include config.json" pyarmor build通过--manifest可以精确选择项目脚本,其模板语法与规则详见下文manifest属性。
强制全量重建
pyarmor build --forcebuild的-B, --force选项(src/pyarmor.py)会跳过增量判断,混淆全部脚本。源码中get_build_files(force=True)直接返回完整文件列表,而不比较mtime与build_time(src/project.py)。
运行混淆后的脚本
cd dist python pybench.py构建产物输出到output(默认dist),其中包含混淆后的脚本与运行时文件;入口脚本已自动插入引导代码(from pytransform import pyarmor_runtime; pyarmor_runtime()),可直接运行。
修改源码后重新构建
cd projects/pybench pyarmor build由于项目记住了上次构建时间(build_time),再次构建只混淆"变更过的脚本"——这正是"增量构建"优势的落地体现。
用不同模式混淆脚本
先配置不同的混淆模式,再重新构建:
pyarmor config --obf-mod=1 --obf-code=0 pyarmor build -B这里-B(即--force)确保所有脚本都以新模式全量重建。obf_mod与obf_code的语义见下文配置文件属性说明。另外在 9.x 中目标选择改为--rft、--mini、--vmc、--ecc等构建目标(src/cli/command.py),这是版本演进带来的差异。
用子项目混淆特殊脚本
场景:项目绝大多数脚本用 restrict mode 3 混淆,但个别脚本需要 restrict mode 2。子项目(child project)就是为此设计的,它通过复制并修改配置文件实现同一源码树下的差异化混淆。
# 1. 在源码路径创建项目并设置 restrict 3 cd /path/to/src pyarmor init --entry foo.py pyarmor config --restrict 3 # 2. 复制配置文件创建子项目 .pyarmor_config-1 cp .pyarmor_config .pyarmor_config-1 # 3. 配置子项目:指定特殊脚本、无入口、restrict 2 pyarmor config --entry "" \ --manifest "include a.py other/path/sa*.py" \ --restrict 2 \ .pyarmor_config-1 # 4. 分别构建主项目与子项目 pyarmor build -B pyarmor build --no-runtime -B .pyarmor_config-1要点解读:
- 子项目就是一份独立的
.pyarmor_config-1配置文件,build命令可以直接接受"项目配置文件名"作为参数(build的project位置参数:Project path, or project configuration file,见 src/pyarmor.py); - 子项目不设入口脚本(
--entry ""),避免引导代码重复插入; - 用
--manifest精确圈定"少数特殊脚本",与主项目的 manifest 互补; - 主项目构建时已生成运行时文件,因此子项目用
--no-runtime跳过运行时生成,避免重复输出;--force确保子项目脚本无论是否变更都被重新混淆。
项目配置文件详解
每个项目都有一份 JSON 配置文件,即项目路径下的.pyarmor_config。以下属性均与 docs.7/project.rst 及 src/project.py 中的默认值对应。
基础属性:name / title / src / output
- name:项目名称。
- title:项目标题。
init时默认与项目目录 basename 相同。 - src:manifest 模板匹配文件的基准路径。可以是绝对路径,也可以是相对项目文件夹的相对路径。
_check()强制要求构建时src解析后为绝对路径且必须存在。 - output:构建输出的保存路径,相对项目路径计算,默认
dist(default_output_path,见 src/config.py)。校验中明确禁止output与src相同,防止混淆产物覆盖源码。
manifest:精确选择要混淆的文件
manifest是一个字符串,指定哪些文件会被混淆,语法与 Python Distutils 的MANIFEST.in一致。默认值为:
global-include *.py即匹配src树中任意位置的.py文件。多个模板指令用逗号分隔,例如:
global-include *.py, exclude __mainfest__.py, prune testinclude/exclude:按路径匹配单个模式;global-include/global-exclude:在整个src树中匹配;prune:排除整个目录树;recursive-include等其余 Distutils 指令同样可用。
数据文件也可以写入 manifest,构建时会被拷贝到输出路径(例如前面的include config.json)。源码层面,Project.build_manifest()借助distutils.filelist.FileList逐条处理模板行并返回文件集合(src/project.py);get_build_files()则在 manifest 基础上追加自动排除项(例如输出路径自身),再按增量策略过滤(src/project.py)。
is_package:按包结构输出
可选值0、1、None。设为1时,src的 basename 会被追加到output作为最终保存路径,但运行时文件仍直接放在output下(src/pyarmor.py)。init时若未指定--type:入口为__init__.py则自动设为1,否则为None。
restrict_mode:限制模式
可选值0、1、2、3、4,默认1。控制混淆脚本的运行限制强度(0 表示不限制;1 为基础限制,防止直接反编译运行;更高数值增强对源码、导入与调用的校验)。注意:若同时使用外部 license,restrict 0与外部 license 冲突(源码会在_check()及构建时抛出'--restrict 0" is conflicted with outer license'异常,src/project.py)。
entry:入口脚本与引导代码
entry是包含一个或多个入口脚本的字符串,入口名相对于src,也支持绝对路径;多入口用逗号分隔:
main.py, another/main.py, /usr/local/myapp/main.py构建时,会为每个入口插入如下引导代码:
from pytransform import pyarmor_runtime pyarmor_runtime()该引导模板定义在 src/config.py。注意:如果 manifest 没有包含某个入口,则该入口可能不被混淆,因此请确保入口脚本在 manifest 匹配范围内。入口脚本还会获得额外的交叉保护代码插入(见cross_protection)。
capsule:项目专用加密钥(已移除)
自 v5.9.0 起移除。早期版本中它表示项目专用 capsule 文件名,相对项目路径解析;新版本统一使用默认 capsule,
config --capsule传入时会被忽略并告警(src/pyarmor.py)。
obf_code:代码对象混淆方式
控制**每个代码对象(code object)**如何混淆:
0:不混淆;1(默认):用默认算法混淆每个代码对象;2:用更复杂的算法混淆每个代码对象。
源码将obf_code、obf_mod与wrap_mode组合映射为最终混淆模式,映射逻辑见Project.map_obfuscate_mode()(src/project.py)。
wrap_mode:代码对象包裹模式
可选值0、1、None,默认1。决定是否用try..finally块包裹代码对象,用于增强反调试与反篡改能力。
obf_mod:模块级混淆方式
控制整个模块代码对象如何混淆:
0:不混淆;1(默认):用 DES 算法混淆模块字节码。
cross_protection:动态库保护
控制混淆脚本中动态库(_pytransform)的保护方式:
0:不保护;1:按默认模板插入保护代码;- 文件名:从指定文件读取保护代码模板,替代默认模板。
--no-runtime构建时若开启保护会告警并自动降级为 0(src/pyarmor.py)。
runtime_path:动态库搜索路径
None或任意路径。运行混淆脚本时去哪里找动态库_pytransform。默认None,表示位于运行时包内或与pytransform.py同目录。典型场景:把混淆脚本打进 zip(如用 py2exe 打包)时,将runtime_path设为空字符串,并把运行时文件拷贝到 zip 同目录即可解决动态库定位问题。该值最终通过encrypt_script(..., rpath=project.runtime_path, ...)写入产物(src/pyarmor.py)。
plugins:扩展 license 类型
None或字符串列表,用于扩展混淆脚本的 license 类型,支持多插件:
plugins: ["check_ntp_time", "show_license_info"]仓库 plugins 目录提供check_ntp_time.py、check_gpu.py、check_docker.py、check_multiple_machine.py等参考插件。
package_runtime:运行时文件组织形式
0:运行时文件与混淆脚本保存在同一路径;1(默认):保存在子路径pytransform中,作为包发布。
enable_suffix:运行时包后缀
v5.8.7 新增。
0(默认):运行时包(模块)名无后缀;1:运行时包(模块)名带后缀,例如pytransform_vax_00001。
用于支持"导入由不同开发者混淆的脚本"时避免运行时包命名冲突。
platform:交叉编译目标平台
v5.9.0 新增。
一个包含一个或多个平台的字符串,多平台用逗号分隔。不进行跨平台混淆时留空。构建时按逗号切分并交给compatible_platform_names()与check_cross_platform()处理(src/pyarmor.py)。
license_file:自定义 license 文件
v5.9.0 新增。
指定除默认 license 之外使用的 license 文件;留空使用默认 license。校验规则要求文件以license.lic结尾或为特殊值outer/no(src/project.py)。
bootstrap_code:引导代码插入方式
v5.9.0 新增。
控制入口脚本引导代码的生成方式:
0:不向入口脚本插入引导代码;1(默认):插入引导代码;若脚本名为__init__.py则用带前导点的相对导入,否则用绝对导入;2:始终在入口脚本中使用不带前导点的绝对导入;3:始终在入口脚本中使用带前导点的相对导入。
源码据此计算relative标志并传给运行时生成与make_entry()(src/pyarmor.py、src/pyarmor.py)。
与新版(PyArmor 9)的对照
仓库同时包含 9.x 的新架构实现(当前仓库版本为 9.2.7,见 src/config.py):
- 新版本仍以"项目"为核心概念,但项目信息改由本地配置文件承载(
[project]节),pyarmor init通过ConfigParser写入src、scripts、modules、packages、excludes、recursive等字段(src/cli/command.py); - 新版本引入
Project/Module/Package/Namespace四类概念模型,将项目拆分为脚本、模块、包与命名空间四类组件(src/cli/project.py); - 构建目标从"模式参数"演变为
--rft、--mini、--vmc、--ecc等目标参数(src/cli/command.py),并新增pyarmor env交互式环境/项目配置命令。
小结与建议
以 Project 方式管理混淆脚本的核心收益在于:一份.pyarmor_config+ 四条命令(init/config/build/info)= 可重复、可增量、可差异化配置的完整混淆工作流。实践建议:
- 优先为每个待交付的应用/包建立独立项目,让
manifest精确圈定交付范围,避免误混淆无关文件; - 善用
--force做全量重建,配合info确认配置后再切换混淆模式; - 需要对少数脚本特殊处理时,复制配置文件创建子项目,主项目负责运行时生成、子项目用
--no-runtime补齐差异化脚本; - 打包进 zip 或需跨平台交付时,重点关注
runtime_path、platform、enable_suffix三个属性。
如需进一步了解混淆模式与限制模式的详细语义,可继续阅读仓库文档 docs.7/mode.rst;运行时与引导代码的实现可参考 src/pytransform.py 与 src/cli/core/runtime.py。
- 开发工具
- 应用安全
【免费下载链接】pyarmor
A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
相关推荐
Buzz 离线语音转文字教程:4 步跑通本地转录与字幕生成
Buzz 离线语音转文字教程:4 步跑通本地转录与字幕生成 会议录音涉密不能传云端,或者想批量产出视频字幕却嫌外包按分钟计费?Buzz 就是为这类场景准备的。它
人工智能语音音频本地部署桌面应用Pyarmor 混淆脚本全解:Bootstrap 脚本、Runtime Package 与 Runtime Key 的协作机制
Pyarmor 混淆脚本全解:Bootstrap 脚本、Runtime Package 与 Runtime Key 的协作机制 本文基于 Pyarmor 官方文
开发工具应用安全PyArmor 使用完全指南:从脚本混淆、License 绑定到打包发布
PyArmor 使用完全指南:从脚本混淆、License 绑定到打包发布 导读 PyArmor 是一款用于混淆 Python 脚本的命令行工具,核心能力是"混淆
开发工具应用安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考