使用项目中的包创建可执行 Zip 存档

Creating Executable Zip Archives With Packages in the Project

我觉得这个问题需要一个更好的标题,如果有人提出更好的建议,我会修改它。问题是我不确定我在这里使用的功能的术语。

描述我的问题的最佳方式是展示我所做的事情。项目在这里:https://github.com/jeffnyman/quendor

此项目已设置,因此可以作为模块执行。例如,有人可以从项目根目录执行此操作:

python3 -m quendor

我还有一个构建脚本来生成 in-memory zip(如果我正确使用该术语):

https://github.com/jeffnyman/quendor/blob/master/build.py

如果你 运行 build.py 它会生成一个 quendor.py 文件来执行整个项目。在我包含其他目录(比如我的 utilitieszinterface)之前,它工作得很好

项目现在在 repo 中,如果你 运行 构建(.\build.py)然后 运行 生成的文件:

./quendor.py

您收到以下错误:

File "./quendor.py/quendor/__main__.py", line 6, in <module>
ModuleNotFoundError: No module named 'quendor.zinterface'

所以一个关键点:如果我的所有文件都在同一个目录中(即在 quendor 中),这个构建脚本在生成可执行脚本文件方面工作正常。

但是一旦我将子目录和文件包含在这些目录中,就会出现上述错误。

我确定正在收集所有文件。我从第 18 行开始处理 (https://github.com/jeffnyman/quendor/blob/master/build.py#L18)。如果您要将此语句添加到第 24 行:

print(f"* {file_path}")

您会看到它输出以下内容:

* quendor/__init__.py
* quendor/__version__.py
* quendor/zinterface/fileio.py
* quendor/utilities/messages.py
* quendor/__main__.py

所以我怀疑这可能与我在第 28 行写入字符串的代码有关 (https://github.com/jeffnyman/quendor/blob/master/build.py#L28)。我觉得我必须做更多的工作才能让可执行压缩脚本文件了解这些模块。

但我不确定 (1) 我是否准确,以及 (2) 即使我是准确的,如果可能的话。我发现我有点头疼了。

如有任何想法,我将不胜感激,我很乐意更新任何必要的说明或术语。

所以它不会让我发表评论,除非我有更多的声誉,但我可以 post 回答。即使我没有答案,而是发表评论。我认为以上评论不是针对您实际的 __main__.py 文件,而是针对您的 quendor.py 文件中生成的文件。您可能想尝试将导入语句添加到您编写的打包字符串中。

例如,如果您在第 32 行添加以下内容,看看会发生什么:import quendor.zinterface.fileio as zio。 (不要替换那里的行。只需放我的行,然后保留其他行。)我不确定 zip 过程是如何工作的,但如果它试图镜像应该工作的模块过程。但是,如果没有,那将不起作用。您可能也只是想尝试做 import quendor.zinterface。这本身是行不通的,但看看它是否会给您带来不同的错误会很有趣。

尝试使用您的存储库中我能想到的几乎所有导入和文件收集变体,有一个好消息/坏消息。

  • 坏消息是答案是:不可能。

  • 好消息是:如果您将所有文件都保存在 quendor 目录中而不是子目录中,那么您确实有一个有效的实现。

另一个好消息是您偶然发现了一些问题,并提出了一个 Python 专家无法回答的问题。从中可以找到一定的乐趣!我保证您不会得到有效的答案("all files in one directory" 解决方案除外)。

对答案的改进是,如果您将程序设置为 运行 作为模块,只需使用 pip 配置即可。这基本上可以做您想要的相同事情,但不必经历扭曲。 (除非有理由让您按照原来的方式进行构建而不是使用 pip。)

原来我找到方法了!它需要使用 os.walk 而不是 os.listdir。这需要采纳这里的人们讨论过的一些想法。这是执行此操作的脚本:

https://github.com/jeffnyman/quendor/blob/master/build.py

您可以将其与我的 previous commit 尝试以不同方式处理此问题进行比较。

Eldritch 是对的,我不能只是展平目录,也不能只是将导入添加到我写入最终 zip 文件的字符串中。 Jean-François 是正确的,我必须关注正在生成的 __main__.py。我的贡献是找出 os.walk() 然后 parameterizing the written string 来处理不同的目录。

最后,根据 HTF 的建议,此解决方案确实需要我在每个包中放置一个空的 __init__.py 文件。

有了我的解决方案,您可以 运行 build.py 然后生成 quendor.py 脚本。然后该脚本在识别对各种包的导入方面正确执行。