How to add images to a program generated by Pyinstaller?

Asked

Viewed 76 times

2

I am creating an executable using the Python programming language and its pyinstaller library. To create the interface, I am using the Tkinter library.

In the executable interface I put an image using code similar to this: How do I add an image to a python script using Tkinter .

However, this code requires the user to have the image on their PC. How do I make it so that the user does not need the image on their PC? That is, I want to send him only the executable and the image still be displayed. It would be possible?

2 answers

4

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.

Reading an added image with --add-binary no Tkinter

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!

  • @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

-4

You can store your image in an "images" folder, together with/.py. Unfortunately, it is not possible to use an image that is not stored on the device...

  • In fact the user can yes with Pyinstaller package a data file by manipulating the specification file the Spec File using the option --add-data as argument a string containing a list of tuples where the first element is the file path and the second is virtual directory. Access the file in Runtime with pkgutil.get_data()

  • 2

    @Augustovasques in the case of image would be add-binary, if I’m not mistaken.

  • @Guilhermenascimento, yes you are correct. The mistake is mine, the correct option to package an image in the executable is --add-binary

Browser other questions tagged

You are not signed in. Login or sign up in order to post.