跳转至

Python 打包的应用程序

REA 静态盘点带有附加 CArchive 的 PyInstaller 可执行文件。 inspect_artifact 和 extract_artifact 通过 CLI 和 MCP 共享同一个读取器。 它们读取归档字节,而无需启动应用程序。字节码源码反编译、加密 PYZ 的恢复、 zipapp 和 PEX 分析不在该能力范围之内。

extract_artifact.coverage 保留清单生成方的源遍历范围与确定性。 成功的发布仅证明所选中的已盘点常规文件已被写入并验证;它并不证明每个源条目 都可表示,也不证明每个嵌入的有效载荷都已被解码。例如,一个包含无效 UTF-8 文件名的目录可以成功发布其可表示的文件,而 coverage 仍为 unknown。 提取操作保留清单的命令来源与局限,以及所选出现项的带路径限定的派生说明。 因此,重建的 .pyc 头部在提取结果中仍会被标识为派生字节。

事实与聚焦查询

根出现项的 format_metadata 记录 CArchive 布局(2.0 或 2.1)、归档与 cookie 偏移量、表范围、条目数、原始 Python 版本、已知时的归一化主/次版本号、库名称和 加密标记。成员元数据保留原始名称、表索引、类型、压缩标志、相对偏移量以及已知的 目录记录范围。逻辑路径遵循载体的路径方言:对于 PE 载体,反斜杠用作路径分隔符; 而对于 POSIX 载体,反斜杠仍是字面文件名符号。源名称始终保留其存储时的拼写。 如果载体方言未确认,REA 会逐字保留反斜杠,而不会推断 POSIX 语义。 relative_offset 对于 CArchive 行而言是相对于 CArchive 起始位置,对于 PYZ 行 而言则是相对于解码后的 PYZ 镜像。CArchive 目录记录起始于 archive_start + toc_offset + directory_record_offset;其大小为 directory_record_size。PYZ 行的目录范围保持未知。 CArchive 类型 b 在通用 executable 事实中保留 PyInstaller 的可执行成员声明; 类型 x 则仍为非可执行。这来源于归档类型代码,而非文件名或成员内容。 不同的 CArchive 行即使共享同一逻辑路径,也保留其表索引身份。清单可以在该路径同时 保留一个文件和一个已解码的 PYZ 目录,包括 PYZ 子项;提取操作会拒绝目标冲突,而不是 静默省略这些子项。

命名空间包在其投影查询路径上仍是元数据声明;它们不声称拥有目标目录。它们的 relative_offset 和 compressed_size 保留旧版生成方声明的任何有效载荷,而 declared_size 为零,因为命名空间不会物化任何字节码。每个已声明的跨度必须在 PYZ 目录表之前结束。 格式错误的 CArchive TOC 行会标识其从零开始的表索引以及 TOC 内的字节偏移,涵盖截断的 头部、无效名称、压缩标志和类型代码。该失败保留其原始格式原因。 PYZ 的 compression_flag 由存储派生而来:非空有效载荷都会被压缩,包括旧版命名空间; 空命名空间没有压缩有效载荷。

CArchive 类型 o 条目是运行时选项。它们是元数据出现项,没有内容工件或可提取文件。 其查询路径为 __pyinstaller__/runtime-options/<table index>;选项文本是 format_metadata.source_name。重复声明保留各自不同的出现项身份。这些路径不声称 拥有输出文件系统名称。

类型 d 条目是多包依赖项。它们同样是元数据,位于 __pyinstaller__/dependencies/<table index> 之下,并且永远不会物化出空文件。 读取器保留原始引用,并将其第一个冒号拆分为 dependency_archive 和 dependency_member。dependency_status 保持为 unresolved;对于格式错误的引用, 则为 invalid-reference,且部分内容未知。external_dependency_count 汇总这些 声明。REA 不会打开另一个可执行文件,也不会声称其内容可用。与元数据具有相同逻辑路径 的真实文件仍可独立提取。 这两种声明类型都要求有效载荷为空且不进行压缩。它们的查询路径不参与文件系统冲突检查、 目录祖先或源映射目标查找;其父级标识声明所在的容器。完整的经认证清单页面集 在任何合并顺序下都保留生成方身份,包括元数据/文件别名。格式错误的 TOC 诊断信息会指名 表索引;原始名称仍可在所提供的工件中获得。路径失败使用有界的转义预览并报告原始长度; 已接受的路径和保留的源名称不会被缩短。

compare_artifacts 使用容器、容器名称、源名称和类型代码,将这些无节点的记录作为声明 进行比较。因此,相同的选项或依赖声明可以比较为无变化,而并不意味着外部依赖的字节已被 找到。对于已物化的 PyInstaller 成员,相同字段独立于内容身份参与元数据增量比较;归档 偏移量和表位置仍是位置事实,而非声明身份。缺失的声明事实和不可用的非元数据内容保持未知。

请求 detail: "summary" 以获得紧凑的检查结果,然后使用 inspect_analysis_view 查询保留的 Evidence。清单视图可以选择 collection: "occurrences"、 entry_kinds: ["metadata"]、精确逻辑路径或出现项 ID、请求的 fields,以及 offset/limit。过滤器取交集;身份、父级 Evidence 和 coverage 在投影后依然保留。 完整的清单 Evidence 仍可导出。紧凑回复会减少返回的上下文;它仍会执行完整的成员清单和 哈希工作。聚焦视图会增加调用和工具模式(tool-schema)开销。一个完整的小型清单总体成本 可能更低;当完整的成员图会使回答超载时,应优先选择紧凑交付。

rea inspect-artifact /absolute/path/hello --detail summary --evidence_output /absolute/new/evidence.json --json
rea extract-artifact /absolute/path/hello --json

解码与证据限制

清单化(inventory)通过有界流对各个成员单独进行哈希。存储的 PYZ 镜像使用描述符范围;外部压缩镜像流式写入私有文件,这些文件由读取者负责管理,包括清理及任何清理重试。提取操作会将所选载体绑定到其清单化摘要,并在读取前后检查来源身份与状态。它不会保留展开后的模块体。不透明的外部压缩镜像在打开时会复用已验证的私有镜像,而不是再次解压载体。直接源区间描述的是存储的 CArchive 字节;解压后的内容没有直接源区间,即使其编码大小与解码大小相同。原始偏移和压缩信息仍作为元数据保留。

仅加载 PYZ 头部和 marshal 目录用于列出。PYZ 表有 16 MiB 预算;CArchive 表有 32 MiB 预算。解析后的事实有 32 MiB 的序列化预算。投影条目共享 64 MiB 的保留预算,包括元数据、簿记,以及对命名空间对象和每个路径组件上可能出现的大小写冲突注解的保守预留。这些预留发生在规范化或字典树分配之前。外部压缩的 PYZ 镜像具有独立的每读取者容量,最多 128 个私有文件,从而限制保留的 inode 和镜像标识。在任何临时文件创建之前,会先确认完整的镜像数量;超出数量的镜像会返回容量错误。这是资源策略,而非 PyInstaller 格式限制。工件错误通过 details.boundary: "capacity" 保留这一区分,并在诊断信息和 details.detail 中给出实际配额。更改输出详细程度不会缩小该配额的输入范围;这些操作不会在清单化过程中选择更窄的成员路径。

只有零字节读取才表示 EOF;成功但较短的描述符读取会填满有界范围。压缩成员必须消耗其完整声明的输入范围;尾随垃圾数据和拼接流会被拒绝。明文扩展具有聚合且源自归档的预算;超出预算会返回资源错误。

支持的最终 Python 字节码魔数覆盖 Python 3.7 至 3.14。受支持的 marshal 目录值为列表、元组、字符串、整数和字节,包括用于模块名的驻留 Unicode 字符串。Unicode 字符串使用 CPython 的 UTF-8 surrogatepass 编码,从而在解码后的模块名中保留单独的代理项码点。目录值遵循已识别的 CPython marshal 语义;例如,最高有效位为零的长整数属于格式错误,不会被规范化为有效的表值。不支持的魔数、或格式错误/不支持的目录,会作为带有限制说明的不透明成员保留,并带有 pyz_status: "opaque";不会从该表投影任何子条目,这些子条目的模块内容保持未知。原始 PYZ 成员及其摘要仍可独立使用。健康的 CArchive 同级成员仍会被清单化。任何不透明的 PYZ 都会使生产者遍历覆盖率未知,包括保留的摘要和已耗尽的查询。每个归档的原因仍保留在不透明事件上;覆盖率观测仅汇总其数量,而不重复每项限制。空结果并不证明模块不存在。即使其 Python 版本未知,观测到的 pyz_python_magic 字节仍然可用。目录声明的是压缩后的模块长度,因此解码数据内部的未压缩声明大小和源区间仍然未知。

PYZ 模块从自身受支持的魔数中获取派生的 16 字节 .pyc 头。仅当所有同级 PYZ 魔数和 cookie 的 Python 版本一致时,CArchive 脚本才会收到该头。在相同的一致条件下,仅当 CArchive 模块(m/M)的解压前缀识别为无头 marshal 代码时,它们才会收到头。保留 .pyc 头的旧式模块,以及前缀无法识别的模块,会保留其原始字节,并报告 bytecode_header: "unknown"。头前缀并不证明整个文件有效。bytecode_magic 和图推导边用于标识合成头;成员摘要覆盖生成的派生文件。这些头不证明成功的执行或反编译。

非空的 CArchive Python 模块 pyimod00_crypto_key(m/M)会被记录为加密标记;同名数据文件或脚本则不会。受影响的 PYZ 数据块会在不解码的情况下报告;提取操作拒绝加密条目。原始 PYZ 容器仍可读取和哈希,即使其模块表不透明。其标记保留在元数据中,不透明子覆盖范围保持未知;提取容器不会解密其载荷。该标记同样适用于非空的旧式命名空间载荷。空命名空间没有可加密的载荷,因此保留空的加密来源。

检测会在最后 16 MiB 内搜索 cookie,允许在该范围内存在尾部 macOS 代码签名。成员偏移相对于归档起点:cookie 位置加上 cookie 大小减去包长度。原生引导加载器分析仍可通过原生工具使用。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea