Reputation: 867
I am trying to bundle an application written in Python and include the relevant data files in the bundle. What is wrong with the way I am adding in data?
This is using a spec file to exclude certain libraries and include data files. I run the cmd pyinstaller --onefile main.spec
# -*- mode: python -*-
block_cipher = None
added_data = [('file_one.pickle', '.'),
('file_two.pickle', '.'),
('file_three.pickle', '.')]
excluded_libraries = [XXX]
a = Analysis(['main.py'],
pathex=['C:\\Users\\XXX\\XXX\\XXX\\XXX\\Folder'],
binaries=[],
datas=added_data,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=excluded_libraries,
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='main')
When I run the .exe
, the program runs until the files I want to bundle are necessary. However, the program runs completely if I place the files in the same directory as the .exe
Upvotes: 1
Views: 1377
Reputation: 6041
The way you are bundling the files are fine but I recommend you to use add-data
flag with the build arguments. I think your problem is with the way you retrieve the files.
According to docs:
When a bundled app starts up, the bootloader sets the sys.frozen attribute and stores the absolute path to the bundle folder in
sys._MEIPASS
. For a one-folder bundle, this is the path to that folder. For a one-file bundle, this is the path to the temporary folder created by the bootloader.
So you bundle the files PyInstaller would extract them in a temporary directory something like C:/Users/<Username>/AppData/Local/Temp/_MEIxxxxxx
. You need to retrieve the files from there.
import os
import sys
def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
if __name__ == "__main__":
file_one_path = resource_path("file_one.pickle")
file_two_path = resource_path("file_two.pickle")
file_three_path = resource_path("file_three.pickle")
Upvotes: 1