Question: How do I use a data file in a pyinstaller built program?
Let's first assume that the python script is currently working when run as a script, and that the following line is in the script:
filename = PhotoImage(file='C:\\Users\\username\\Downloads\\TripApp\\BgSM.gif')
This line indicates that the script is retrieving a file from a fixed directory (probably not best practice, but fine for an example), and turning that .gif
file into a PhotoImage()
object instance. This will be our baseline.
There will need to be three things done to successfully use this file when our script is run as a pyinstaller
built program.
1. During the pyinstaller build, move the file to a known location
This step is accomplished by adding a datas
directive to the `.spec' file. See this post for more info on how to do that. But in short, this will be needed:
datas=[
('C:\\Users\\test\\Downloads\\TripApp\\BgSM.gif', 'data'),
...
],
Please note that there are two elements in the tuple. The first element is the path of our .gif
file as it exists in the working python script before we packaged it into a pyinstaller executable. The second element of the tuple is the directory that the file will be in when the executable is run.
2. At runtime, find our .gif
file
Here is the function from the example in the question, recast to use:
- The absolute path from the example, when the script is run as a script or,
- The path specified in the
datas
tuple when the script is run as a pyinstaller built program.
Code:
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS,
# and places our data files in a folder relative to that temp
# folder named as specified in the datas tuple in the spec file
base_path = os.path.join(sys._MEIPASS, 'data')
except Exception:
# sys._MEIPASS is not defined, so use the original path
base_path = 'C:\\Users\\test\\Downloads\\TripApp'
return os.path.join(base_path, relative_path)
3. Recast the baseline to work in our pyinstaller built program
So now that we can construct a path to our .gif
file when run as a script, or as a pyinstaller built program, our baseline becomes:
filename = PhotoImage(file=resource_path('BgSM.gif'))