Search code examples
pythonexecutablepyinstallercx-freeze

How to use Pyinstaller - cx_Freeze executable sys.MEIPASS/sys.executable


I've been working on getting a python executable working for OSX El Capitan, and i successfully get the executable built using both Pyinstaller and cx_Freeze, the issue comes when i actually run the executable on another mac. The error i get is about not being able to find the .db file referenced in my main script, so i looked at documentation for both programs and came across sys.MEIPASS (Pyinstaller) and sys.executable (cx_Freeze) to include data files in the --onefile app. This is the code i used in my main script:

def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys._MEIPASS) #in cx_Freeze this is sys.executable     
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = ospath.abspath(os.pardir)

    return os.path.join(datadir, filename)

#This is how im using the "find_data_file" function in my code. 
dbpath = find_data_file('PubData.db')
conn = lite.connect(dbpath)

ive changed it a bit in the else statement to match the layout of my project directories, and it works perfectly fine when running an unfrozen application. However when i try to run using the built executable it gives me an error about not being able to find the .db file, which i thought referencing sys.MEIPASS or sys.executable would fix.

Error:

Traceback (most recent call last):
  File "interface/GUI.py", line 673, in <module>
  File "interface/GUI.py", line 82, in __init__
  File "interface/GUI.py", line 212, in getServerNames
sqlite3.OperationalError: no such table: servernames

This is how my file tree looks:

PubData-master ##(Project Root Directory)
   Interface ##(Directory)
      GUI.py ##(Main Script, this is where i reference 'PubData.db')
      GUI.spec ##(Pyinstaller spec file)
   PubData.db  ## This is my database file, in the PubData-master Directory

If anyone could tell me what i am doing wrong, or give me a solution, i would be extremely grateful!


Solution

  • if you are trying to access any data file you specified in the .spec file, in your code, you must use Pyinstaller's _MEIPASS folder to reference your file. Here is how i did so with the file named Data.db:

    import sys
    import os.path
    
            if hasattr(sys, "_MEIPASS"):
                datadir = os.path.join(sys._MEIPASS, 'Data.db')
            else:
                datadir = 'Data.db'
    
            conn = lite.connect(datadir)
    

    this replaced the following single line:

    conn = lite.connect("Data.db")
    

    This link explained it very well: https://irwinkwan.com/2013/04/29/python-executables-pyinstaller-and-a-48-hour-game-design-compo/