Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining application path in a Python EXE generated by pyInstaller

I have an application that resides in a single .py file. I've been able to get pyInstaller to bundle it successfully into an EXE for Windows. The problem is, the application requires a .cfg file that always sits directly beside the application in the same directory.

Normally, I build the path using the following code:

import os config_name = 'myapp.cfg' config_path = os.path.join(sys.path[0], config_name) 

However, it seems the sys.path is blank when its called from an EXE generated by pyInstaller. This same behaviour occurs when you run the python interactive command line and try to fetch sys.path[0].

Is there a more concrete way of getting the path of the currently running application so that I can find files that are relative to it?

like image 263
Soviut Avatar asked Jan 01 '09 08:01

Soviut


People also ask

How do I check my PyInstaller path?

To determine application path in a Python EXE generated by pyInstaller, we can check the sys. frozen property. If the value is True , then the script code is running in the exe file.

How do I get the Python application path?

To retrieve a file in Python, you need to know the exact path to reach the file, in Windows, you can view a particular file's path by right-clicking the File-> Properties-> General-> Location. Similarly, to run a script, the working directory needs to be set to the directory containing the script.

Where does PyInstaller save exe?

PyInstaller generates the executable that is a bundle of your game. It puts it in the dist\ folder under your current working directory.


2 Answers

I found a solution. You need to check if the application is running as a script or as a frozen exe:

import os import sys  config_name = 'myapp.cfg'  # determine if application is a script file or frozen exe if getattr(sys, 'frozen', False):     application_path = os.path.dirname(sys.executable) elif __file__:     application_path = os.path.dirname(__file__)  config_path = os.path.join(application_path, config_name) 
like image 192
Soviut Avatar answered Sep 25 '22 02:09

Soviut


According to the documentation of PyInstaller, the suggested method of recovering application path is as follows:

#!/usr/bin/python3 import sys, os if getattr(sys, 'frozen', False):     # If the application is run as a bundle, the PyInstaller bootloader     # extends the sys module by a flag frozen=True and sets the app      # path into variable _MEIPASS'.     application_path = sys._MEIPASS else:     application_path = os.path.dirname(os.path.abspath(__file__)) 

Tested for PyInstaller v3.2, but this certainly has been working for earlier versions as well.

Soviut's solution does not work, at least not in general for recent versions of pyInstaller (note that the OP is many years old). For instance, on MacOS, when bundling an application into a one-file-bundle, sys.executable points only to the location of the embedded archive, which is not the location where the application actually runs after the pyInstaller bootloader has created a temporary application environment. Only sys._MEIPASS correctly points to that location. Refer to this doc-page for further information on how PyInstaller works.

like image 43
normanius Avatar answered Sep 26 '22 02:09

normanius