在使用 PyInstaller 创建的单文件 exe 中导入外部模块 [英] Importing external module in single-file exe created with PyInstaller

查看:20
本文介绍了在使用 PyInstaller 创建的单文件 exe 中导入外部模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 PyInstaller 创建一个单文件可执行文件.我的脚本是否可以执行导入,以便 i) 导入的模块从与 exe 相同的目录导入(即它没有打包到 exe 中)和 ii) 导入的模块可以导入其他模块 打包成exe了吗?

I am using PyInstaller to create a single-file executable. Is it possible for my script to perform an import such that i) the imported module is imported from the same directory as the exe (i.e. it's not packaged into the exe) and ii) that imported module can import other modules that were packaged into the exe?

这里的背景是导入的模块包含用户应该能够修改的配置.这可能包括创建自定义派生类和使用来自打包模块的枚举.

The background here is that the imported module contains configuration that the user should be able to modify. This may include creation of custom derived classes and use of enums from the packaged modules.

我没有找到任何关于此的建议,尽管搜索起来很困难,因为有太多使用基本相同关键字的相似主题.

I haven't found any advice on this, though it's a difficult search because there are so many similar topics that use basically the same keywords.

推荐答案

以下步骤允许导入 PyInstaller 创建的可执行文件之外的 Python 模块(此处名为 module_name)并用于该模块导入捆绑到可执行文件中的模块.

The following steps allow a Python module (named module_name here) outside of an executable created by PyInstaller to be imported and for that module to import modules that were bundled into the executable.

  • excludes=['module_name'] 添加到 PyInstaller 规范中使用的分析对象.这可以防止 module_name.py 被捆绑到可执行文件中.
  • 添加 sys.path.append(os.path.dirname(sys.executable)) 其中 module_name 在您的应用程序中导入.这允许它从可执行文件所在的目录导入,该目录不同于应用程序将在其中运行的目录(因为被解压到一个临时文件夹).
  • 确保外部模块执行的任何导入也由捆绑模块之一执行导入外部模块之前.解释器不会根据捆绑模块解析外部模块的导入,但使用 sys.modules 中已经存在的模块.
  • Add excludes=['module_name'] to the Analysis object used in the PyInstaller spec. This prevents module_name.py being bundled into the executable.
  • Add sys.path.append(os.path.dirname(sys.executable)) where module_name is imported in your application. This allows it to be imported from the directory the executable is in, which is different to the directory that the application will run in (due to being decompressed to a temporary folder).
  • Make sure any imports performed by the external module are also performed by one of the bundled modules before the external one is imported. The interpreter will not resolve the external module's imports against bundled modules, but will use ones that already exist in sys.modules.

作为最后一点的示例,请考虑以下内容.

As an example of the final point, consider the following.

# bundled_module1.py
import external_module

# bundled_module2.py
# module content

# external_module.py
import bundled_module2

这将在 external_module.py 中失败,因为无法找到导入的模块.但是,以下内容将起作用:

This will fail in external_module.py because the imported module can't be found. However, the following will work:

# bundled_module1.py
import bundled_module2
import external_module

# bundled_module2.py
# module content

# external_module.py
import bundled_module2

如果外部模块应该能够导入一组有限的捆绑模块,这会很好.对于较大的集合,它可能会变得笨拙.

This will be fine if there are a limited set of bundled modules that the external one should be able to import. It may get unwieldy for larger sets.

鉴于文档指出解释器解决针对捆绑到可执行文件中的模块的导入,这感觉像是一个可能的错误.与可执行文件之外的模块互操作虽然没有明确调用.

Given that the documentation states that the interpreter will resolve imports against modules bundled into the executable, this feels like a possible bug. Interoperating with modules outside of the executable isn't explicitly called out though.

这篇关于在使用 PyInstaller 创建的单文件 exe 中导入外部模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆