2

我刚刚发现 (A) 一个 ZIP 文件可以直接作为 Python 二进制文件的script参数(通常.py会传递一个文件)传递,并且 (B) ZIP 文件可以有任何后缀,甚至.py可以被识别为 ZIP文件(至少在 Mac OS X 上的命令行和 Windows 上的命令行和 GUI,它似乎工作)。实现这一点的整个故事都记录在这个问题中。

这似乎对 Python 应用程序的分发非常有吸引力,因为安装程序不受欢迎,并且它具有与.jar我们的用户习惯的存档相同的使用特性(无需安装,可以通过电子邮件发送而无需进一步存档)。命名 ZIP 存档.py(或.pyw)无需在客户端机器上进行任何配置即可启用此行为,除了安装 Python。

我的问题是我只能找到我发现的 (A) 部分的文档,但不能找到 (B) 部分的文档。所以我的第一个问题是 Python 如何检测作为script参数传递的文件是 ZIP 存档而不是 Python 源文件?是否存在任何可能会随机中断的启发式方法,例如当 ZIP 存档包含一些特殊内容时(例如,看起来像 Python 代码的未压缩文件)?

第二个问题是当应用程序携带大量非代码数据文件(数十 MB)时,这种方法是否存在任何缺点,除了对这些文件的访问不透明这一事实。如果 ZIP 文件很大和/或包含很多文件,我正在考虑 ZIP 文件检测需要更长的时间。

更新

遗憾的是,到目前为止所有的答案(Joachim Sauer 的、Keith Randall 的和 Curious 的)都是错误的。Zip 规范不要求 ZIP 文件必须以特定的标头开头。Zip 文件可以在其前面添加任何数据,并且仍然是有效的 Zip 文件(这是自解压 Zip 文件的工作方式,其中文件以 Windows EXE 标头而不是任何特定于 Zip 的文件开头)。这在好奇的答案中链接的页面中进行了解释。

我猜 Python 解释器会查找 Zip 中央目录,如果有,该文件将用作 Zip 文件而不是 Python 源文件。有没有人想在他/她的答案中包含这个,以便我接受?

4

2 回答 2

2

所有 ZIP 文件(以及所有派生格式,例如 .jar 文件)都以 ASCII 字符“PK”开头(以及另外两个不构成有意义的 ASCII 字符的字节)。

这些被称为幻数,是在没有外部信息(文件扩展名或 mime 类型)的情况下检测文件类型的常用方法。

由于只需要读取最开始的字节,因此无论档案有多大,检测文件是否为 ZIP 文件的速度同样快。检测 ZIP 文件是否正确且未损坏是另一回事,但除非明确要求,否则通常不会这样做。

于 2012-08-29T07:15:38.040 回答
1

Zip 文件通常不通过文件扩展名识别,而是通过文件开头的幻数识别。前 4 个字节始终是0x50 0x4b 0x03 0x04.

于 2012-08-29T07:16:44.267 回答