python - PyInstaller,如何从 pip 安装的外部包中包含数据文件?

标签 python python-3.5 pyinstaller

问题

我正在尝试使用 PyInstaller 创建一个供我公司内部使用的应用程序。该脚本在工作 python 环境中运行良好,但在转换为包时丢失了一些东西。

我知道如何在我的包中包含和引用我自己需要的数据文件,但我在包含或引用导入时应该包含的文件时遇到问题。

我正在使用一个名为 tk-tools 的 pip 可安装包,其中包括一些用于面板式显示器(看起来像 LED)的漂亮图像。问题是,当我创建一个 pyinstaller 脚本时,每当引用其中一个图像时,我都会收到错误消息:

DEBUG:aspen_comm.display:COM23 19200
INFO:aspen_comm.display:adding pump 1 to the pump list: [1]
DEBUG:aspen_comm.display:updating interrogation list: [1]
Exception in Tkinter callback
Traceback (most recent call last):
  File "tkinter\__init__.py", line 1550, in __call__
  File "aspen_comm\display.py", line 206, in add
  File "aspen_comm\display.py", line 121, in add
  File "aspen_comm\display.py", line 271, in __init__
  File "aspen_comm\display.py", line 311, in __init__
  File "lib\site-packages\tk_tools\visual.py", line 277, in __init__
  File "lib\site-packages\tk_tools\visual.py", line 289, in to_grey
  File "lib\site-packages\tk_tools\visual.py", line 284, in _load_new
  File "tkinter\__init__.py", line 3394, in __init__
  File "tkinter\__init__.py", line 3350, in __init__
_tkinter.TclError: couldn't open "C:\_code\tools\python\aspen_comm\dist\aspen_comm\tk_tools\img/led-grey.png": no such file or directory

我查看了最后一行的那个目录 - 这是我的发行版所在的位置 - 发现不存在 tk_tools 目录。

问题

如何让pyinstaller收集导入包的数据文件?

规范文件

目前,我的 datas 是空白的。使用 pyinstaller -n aspen_comm aspen_comm/__main__.py 创建的规范文件:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['aspen_comm\\__main__.py'],
             pathex=['C:\\_code\\tools\\python\\aspen_comm'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)

pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)

exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='aspen_comm',
          debug=False,
          strip=False,
          upx=True,
          console=True )

coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='aspen_comm')

当我查看 /build/aspen_comm/out00-Analysis.toc/build/aspen_comm/out00-PYZ.toc 时,我发现一个条目看起来像它找到了 tk_tools 包。此外,tk_tools 包的某些功能在到达查找数据文件之前可以完美运行,所以我知道它被导入到某个地方,我只是不知道在哪里。当我搜索 tk_tools 时,我在文件结构中找不到对它的引用。

我也尝试了 --hidden-imports 选项,结果相同。

部分解决方案

如果我使用 datas = [('C:\\_virtualenv\\aspen\\Lib\\site-packages\\tk_tools\\img\\', 'tk_tools\\img\\')]Analysis 中的 datas=datas,然后一切都按预期工作。这会起作用,但我宁愿 PyInstaller 找到包数据,因为它已明确安装。我会继续寻找解决方案,但目前 - 我可能会使用这种不理想的解决方法。

如果您可以控制包裹...

然后你可以使用stringify在子包上,但这仅适用于您自己的包。

最佳答案

我利用 spec 文件是执行的 Python 代码这一事实解决了这个问题。您可以在 PyInstaller 构建阶段动态获取包的根,并在 datas 列表中使用该值。就我而言,我的 .spec 文件中有这样的内容:

import os
import importlib

package_imports = [['package_name', ['file0', 'file1']]

datas = []
for package, files in package_imports:
    proot = os.path.dirname(importlib.import_module(package).__file__)
    datas.extend((os.path.join(proot, f), package) for f in files)

并使用生成的 datas 列表作为 Analysis 的参数。

关于python - PyInstaller,如何从 pip 安装的外部包中包含数据文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46474588/

相关文章:

python - 有条件地修改多个变量

python - 如何使用pyinstaller将多个python文件编译成单个.exe文件

python - 当提供 'n' URL 时查找特定类型的 URL

python - 应用引擎,Python : Send Mail function

python - Pymysql无法导入python3

Python While 循环 - 变量未更新?

python - pygame.display.set_mode 窗口打开但卡住 python 3.5 mac osx 10.11.1

python - pyinstaller 3.2 与 django 1.10.1

python - 有没有办法将 pptx-python 与 python 3.7 版本一起使用并使用 pyinstaller 生成 exe?

python - "and"与 Python 中的集合的行为