Bundling data files with PyInstaller (--onefile) Bundling data files with PyInstaller (--onefile) python python

Bundling data files with PyInstaller (--onefile)


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)


pyinstaller unpacks your data into a temporary folder, and stores this directory path in the _MEIPASS2 environment variable. To get the _MEIPASS2 dir in packed-mode and use the local directory in unpacked (development) mode, I use this:

def resource_path(relative):    return os.path.join(        os.environ.get(            "_MEIPASS2",            os.path.abspath(".")        ),        relative    )

Output:

# in development>>> resource_path("app_icon.ico")"/home/shish/src/my_app/app_icon.ico"# in production>>> resource_path("app_icon.ico")"/tmp/_MEI34121/app_icon.ico"


All of the other answers use the current working directory in the case where the application is not PyInstalled (i.e. sys._MEIPASS is not set). That is wrong, as it prevents you from running your application from a directory other than the one where your script is.

A better solution:

import sysimport osdef resource_path(relative_path):    """ Get absolute path to resource, works for dev and for PyInstaller """    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))    return os.path.join(base_path, relative_path)