Have 2 steps to follow, first add the file to the "packaged", you can do this in two ways:
Using the parameters --add-data
and --add-binary
The --add-data
should be used for non-binary files such as plain text files, example:
pyinstaller --add-data=origem:destino foobar.py
Use the pkg_resources.resource_filename
pyinstaller --add-data=origem;destino foobar.py
In Windows use the ;
in Linux and Macos use the :
, example:
pyinstaller --add-data="/home/example/foo.txt:." --add-data="/home/example/bar.txt:." example.py
To separate the origin of the destination. The --add-data
can be used multiple times, example to add two files on Windows:
pyinstaller --add-data="C:\Users\new_g\Desktop\xyz\foo.txt;." --add-data="C:\Users\new_g\Desktop\xyz\bar.txt;." example.py
Note that after the ;
used the .
, the point refers to the initial path of the "within" of the program, if you want to add the file to a subfolder, for example by calling it assets
you can do something like:
pyinstaller --add-data="C:\Users\new_g\Desktop\xyz\foo.txt;assets" --add-data="C:\Users\new_g\Desktop\xyz\bar.txt;assets" example.py
To add binary files use --add-binary
, whole process is the same as previous, only changes you should use for files like images, videos, compressed (gz, zip, rar, 7z, etc), example:
pyinstaller --add-binary="C:\Users\new_g\Desktop\xyz\foo.jpg;assets" --add-binary="C:\Users\new_g\Desktop\xyz\bar.png;assets" example.py
Note: If you want to add everything within a single .exe
use the
parameter --onefile, example:
pyinstaller --onefile --add-binary="C:\Users\new_g\Desktop\xyz\foo.jpg;assets" --add-binary="C:\Users\new_g\Desktop\xyz\bar.png;assets" example.py
Reading the file
Now it is the second step, this is independent of being using Kivy, Tkinter, or simply a Python script without GUI (graphical interface), to read the file one must use lib pkg_resources.resource_filename
, in Windows installations usually comes already installed, but if you do not have the pkg_resources
execute the command:
pip install setuptools
After installing in your script you will read the file so (independent of running python exemple.py
or execute to execute the .exe
generated, example:
from pkg_resources import resource_filename
resource_1 = resource_filename(__name__, 'foo.txt')
resource_2 = resource_filename(__name__, 'bar.txt')
print('resource_1:', resource_1)
print('resource_2:', resource_2)
print(resource_1)
print(__name__)
with open(resource_1) as file:
print(file.read())
print('----------')
with open(resource_2) as file:
print(file.read())
This is a fully adaptable example to any lib, like Tkinter, because the pkg_resources.resource_filename()
returns the absolute path of the file.
In the following example you can read the file foo.png
and display on a label
from pkg_resources import resource_filename
from tkinter import Tk, Label, PhotoImage
root = Tk()
resource_1 = resource_filename(__name__, 'foo.png')
photo = PhotoImage(file=resource_1)
message = Label(root, image=photo)
message.pack()
root.mainloop()
Thank you for the detail in your reply. I still had a question: Even following this procedure, the executable only runs successfully if I put the images inside the folder that it is. Is that normal? I thought this procedure would generate a fully standalone executable, which would not need the images anywhere else. Maybe I’m wrong anyway. Thanks again!
– Augusto Rodrigues
@Augustorodrigues did not understand, the example I demonstrated does not have the images in the same place, I took the images from other places, I think you are confusing things, what you really want is the parameter
pyinstaller --onefile ... example.py
(change the ... by --add-Binary), this will make create an . exe without the separate files– Guilherme Nascimento