Problem
I am attempting to use PyInstaller to create an application for internal use within my company. The script works great from a working python environment, but loses something when translated to a package.
I know how to include and reference data files that I myself need within my package, but I am having trouble including or referencing files that should come in when imported.
I am using a pip-installable package called tk-tools, which includes some nice images for panel-like displays (looks like LEDs). The problem is that when I create a pyinstaller script, any time that one of those images is referenced, I get an error:
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
I looked within that directory in the last line - which is where my distribution is located - and found that there is no tk_tools
directory present.
Question
How to I get pyinstaller to collect the data files of imported packages?
Spec File
Currently, my datas
is blank. Spec file, created with 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')
When I look within /build/aspen_comm/out00-Analysis.toc
and /build/aspen_comm/out00-PYZ.toc
, I find an entry that looks like it found the tk_tools
package. Additionally, there are features of the tk_tools
package that work perfectly before getting to the point of finding data files, so I know that it is getting imported somewhere, I just don't know where. When I do searches for tk_tools
, I can find no reference to it within the file structure.
I have also tried the --hidden-imports
option with the same results.
Partial Solution
If I 'manually' add the path to the spec file using datas = [('C:\\_virtualenv\\aspen\\Lib\\site-packages\\tk_tools\\img\\', 'tk_tools\\img\\')]
and datas=datas
in the Analysis
, then all works as expected. This will work, but I would rather PyInstaller find the package data since it is clearly installed. I will keep looking for a solution, but - for the moment - I will probably use this non-ideal workaround.
If you have control of the package...
Then you can use stringify on the subpackage, but this only works if it is your own package.