Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bundling data files with PyInstaller (--onefile)

I'm trying to build a one-file EXE with PyInstaller which is to include an image and an icon. I cannot for the life of me get it to work with --onefile.

If I do --onedir it works all works very well. When I use --onefile, it can't find the referenced additional files (when running the compiled EXE). It finds the DLLs and everything else fine, just not the two images.

I've looked in the temp-dir generated when running the EXE (\Temp\_MEI95642\ for example) and the files are indeed in there. When I drop the EXE in that temp-directory it finds them. Very perplexing.

This is what I've added to the .spec file

a.datas += [('images/icon.ico', 'D:\\[workspace]\\App\\src\\images\\icon.ico',  'DATA'), ('images/loaderani.gif','D:\\[workspace]\\App\\src\\images\\loaderani.gif','DATA')]      

I should add that I have tried not putting them in subfolders as well, didn't make a difference.

Edit: Marked newer answer as correct due to PyInstaller update.

like image 251
Arboreal Shark Avatar asked Oct 06 '11 13:10

Arboreal Shark


People also ask

What is Onefile in PyInstaller?

When we specify the onefile option, to the PyInstaller, it unpacks all the files to a TEMP directory, executes the file, and later discard the TEMP folder. When you specify the add-data option along with onefile, then you need to read the data referred to in the TEMP folder.

How do you add binary to PyInstaller?

You can add binary files to the bundle by using the --add-binary command option, or by adding them as a list to the spec file. In the spec file, make a list of tuples that describe the files needed. Assign the list of tuples to the binaries= argument of Analysis.

Does PyInstaller include all dependencies?

PyInstaller can bundle your script and all its dependencies into a single executable named myscript ( myscript.exe in Windows). The advantage is that your users get something they understand, a single executable to launch.


1 Answers

Newer versions of PyInstaller do not set the env variable anymore, so Shish's excellent answer will not work. Now the path gets set as sys._MEIPASS:

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) 
like image 110
max Avatar answered Sep 19 '22 13:09

max