Reputation: 73
I am trying to build a one file exe with pyinstaller but I am not sure what the file paths for the images should be in the main python file.
At the top of my main python file I used the MEIPASS 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
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
This is the current code I have for each image file:
root.iconbitmap('C:\\Users\\username\\Downloads\\TripApp\\BennySM.ico')
filename = PhotoImage(file = 'C:\\Users\\username\\Downloads\\TripApp\\BgSM.gif')
I know these are not the best file paths but I am not sure what I need to add so the python file knows where to look. The images bundle with the exe and if I add the exe to the data file it finds the images and runs.
Thank you! I tried adding resource_path before but I was missing the file path in the define section at the top.
Thanks again!
Upvotes: 4
Views: 5317
Reputation: 49784
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:
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'))
Upvotes: 4