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)