Pyinstaller embed images folder in –onefile –windowed application

Question:

I am trying to embed a folder with images into generated (with PyInstaller) executable. But it doesn’t work for me. Even with one simple image!

The datas variable in my main.spec file looks like this:

datas=[ ('C:\Users\<user>\dir1\dir2\MyApp\images\*.png', 'images') ],

According to the documentation:

The first string specifies the file or files as they are in this system now. The second specifies the name of the folder to contain the
files at run-time.

In the python file I read the image like this:

self.SetIcon(wx.Icon("images\myicon.png"))

Finally, this is how I package everything in the *.exe using PyInstaller:

pyinstaller --onefile --windowed --icon=imagesmain32x32.ico main.spec

I am getting the following error:

Failed to load image from file "imagesmyicon.png"

Could someone tell me what I’m doing wrong?

Asked By: Dan A.S.

||

Answers:

When you want to embed a file into your executable, you need to do two steps:

First, add it with add-data to your executable (as you already did). Second, load the file from the extracted path on runtime.

You are trying to load the file from images/myicon.png, and the path is next to your executable. Still, the file is not there, and meanwhile, the runtime files would be extracted in a temp directory, e.g. C:/Users/<user>/AppData/Local/Temp/_MEIXXX. So it needs to be loaded from that directory.

You can use sys._MEIPASS to get the temp path where the extracted files are located. Moreover, you can create a function to load external files:

import os
import sys


def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)


self.SetIcon(wx.Icon(resource_path("images/myicon.png")))
Answered By: Masoud Rahimi