我也是第一次尝试构建一个包含数据文件的简单的--onefile exe,但是在构建.exe时Pyinstaller似乎没有找到它们。一个--onedir build似乎工作正常。
此时我也在使用--debug开关。我能够运行onefile可执行文件,可以看到它似乎开始工作。程序找到(sys._MEIPASS)临时目录ok(按照指示打印所需的目录名称),但在从temp目录中查找第一个数据文件时报告“没有这样的文件或目录”错误。我在.exe上使用了archiveviewer.py而DID却找不到所需的数据文件 - 这似乎是问题所在,但我无法弄清楚原因。构建的数据文件位于spec文件描述的目录中。我的完整spec文件是
# -*- mode: python -*-
a = Analysis(['develop6.py'],
pathex=['C:\\PYINST20'],
hiddenimports=[],
hookspath=None)
a.datas += [ ('conlist.txt', 'C:\\pyinst20\\conlist.txt', 'DATA'), ('imageblank.gif', 'C:\\pyinst20\\imageblank.gif', 'DATA')]
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name=os.path.join('dist', 'develop6.exe'),
debug=True,
strip=None,
upx=True,
console=True )
答案 0 :(得分:1)
在confusing stack overflow threads和Pyinstaller文档之间前后移动后,我终于捆绑了我的应用。
在您的应用根目录和. venv/bin/activate
d:
➜ ~ pip install pyinstaller
➜ ~ pyi-makespec --windowed --onedir --i ./resources/img/icn.icns \
--osx-bundle-identifier "com.myname.macOS.myappname" app.py
现在,稍微修改一下app.spec
:
added_files = [
('resources/img', 'resources/img'),
( 'README.md', '.' )
]
使用资源的相对路径初始化dictionary added_files
并设置datas = added_files
。在我的应用程序中,我使用位于./resources/img
相对于我的main.py文件的图像。
最终,这可能是最容易忘记的步骤而不是那么明显:
➜ ~ pyinstaller --onefile app.spec
请注意,最后一步取自here。
答案 1 :(得分:1)
(这个问题很旧,但这是我发现解决同一问题的唯一途径之一,我将在这里分享我的解决方案,以防它可以帮助某人)
要以--onefile模式将数据文件添加到脚本中,需要做两件事。
在脚本中,调整路径以查找捆绑软件中的数据文件。 根据PyInstaller文档here,可执行文件是从临时文件启动的,因此您的路径必须处理此动态部分:
对于具有以下相对路径的文件: ./your/file/is/here.ext
代码为:
import sys
wd = sys._MEIPASS
file_path = os.path.join(wd,<your>,<file>,<is>,<here>)
注意:要使您的代码也可以在其他上下文中工作,可以执行以下操作:
import sys
import os
try:
wd = sys._MEIPASS
except AttributeError:
wd = os.getcwd()
file_path = os.path.join(wd,<your>,<file>,<is>,<here>)
根据PyInstaller文档here,有两种方法可将数据文件添加到包中:
从脚本目录运行--add-files
时,将选项pyinstaller <yourscript.py>
和文件作为参数传递
首先通过导航到脚本目录并运行pyi-makespec <yourscript.py>
来生成规格文件,然后将文件添加到元组列表data=[]
中。
元组包含文件的实际路径以及其中的路径
您的捆绑包。如果您遵循了第一点,应该看起来像
datas = [('/your/file/is/here.ext','/your/file/is/')]
然后根据您的规格文件运行PyInstall <yourscript.spec>
来构建捆绑包。
答案 2 :(得分:0)
我相信我发现了问题,它与spec文件的正文无关。在使用spec文件运行pyinstaller时,我的命令行语法看起来是错误的。运行正常时:
pyinstaller.py [options] <my_specfile.spec>
似乎有效。
答案 3 :(得分:0)
无论脚本是否捆绑运行,我们都可以按照document设置不同的文件路径。但是,我的解决方法是在所有非脚本文件都存在的地方建立一个稳定的顶层目录,并与所有模块共享该顶层目录。然后,在每个模块中,我可以基于顶层目录创建文件路径。
例如,在此布局中,所有模块代码都位于src
文件夹中。这些模块要求访问conf
文件夹,database
文件夹和otherconfig.yaml
。
├── conf
│ └── config.ini
├── database
├── entry_point.py
├── otherconfig.yaml
├── root_path.py
└── src
├── pkg1
└── pkg2
root_path.py
看起来像这样:
import os
path = os.getcwd()
在每个模块中,我可以为配置文件创建文件路径,如下所示:
import root_path
config_path = f"{root_path.path}/conf/config.ini"
otherconfig_path = f"{root_path.path}/otherconfig.yaml"
然后,在通过pyinstaller -F entry_point.py
创建一个文件可执行文件(不添加任何文件)之后,我们只需要重新创建相同的布局,每个模块中的文件路径仍然可以使用。
├── bundled_executable
├── conf
│ └── config.ini
├── database
└── otherconfig.yaml
当然,此替代方法无法隐藏配置文件。但是对于我的用例,我需要给用户自由修改配置文件的权限,以免隐藏文件对我真正有用。
答案 4 :(得分:0)