Clive
Clive

Reputation: 89

Pyinstaller 3 adding datafiles with --onefile

I have a working Python 3 script, inventoryScraper.py, that I am trying to make into a 1 file executable I can distribute. I have been using Pyinstaller 3 with Python 3, it has worked in the past. I have a file 'Store_Codes.csv' that my script needs to run, and I want it included inside the executable.

I have read and attempted all the previous answers relating to this, and it has not worked/I messed it up. The resulting .exe works when the Store_Codes.csv is in the same folder as the exe, but not otherwise. I am definitely a novice to Python, but the person I'm giving this to has no experience whatsoever with command lines or anything related, so it's important it be an all-in-one file.

I have modified the spec file in every way I have seen on other posts, and none have worked, I am sure I am misunderstanding, and I could really use the help.

What is the straightforward way, with Pyinstaller 3, to include data files in a onefile exe?

Thank you!

Upvotes: 4

Views: 4145

Answers (2)

Rafael
Rafael

Reputation: 473

  1. Put the Store_Codes.csv in the same folder as the .py file.
  2. On the field data in the .spec file you add datas=[( 'Store_Codes.csv', '.' )],
  3. You should add to your .py file

     if getattr(sys, 'frozen', False):
         # if you are running in a |PyInstaller| bundle
         extDataDir = sys._MEIPASS
         extDataDir  = os.path.join(extDataDir, 'Store_Codes.csv') 
         #you should use extDataDir as the path to your file Store_Codes.csv file
     else:
         # we are running in a normal Python environment
         extDataDir = os.getcwd()
         extDataDir = os.path.join(extDataDir, 'Store_Codes.csv') 
         #you should use extDataDir as the path to your file Store_Codes.csv file
    
  4. compile the file.

Discussion

When you start the .exe it creates a temporary folder in the appropriate temp-folder location for the OS. The folder is named _MEIxxxxxx, where xxxxxx is a random number. All the files you need to run the script will be there The sys._MEIPASS is the path for this temporary folder.

When you add datas=[( 'Store_Codes.csv', '.' )] to your spec file. It will copy the file to the main folder of the bundle. If you want to keep it organized you can create a different folder using datas=[( 'Store_Codes.csv', 'another_folder' )], then in your code you would have

 if getattr(sys, 'frozen', False):
     # if you are running in a |PyInstaller| bundle
     extDataDir = sys._MEIPASS
     extDataDir  = os.path.join(extDataDir,another_folder, 'Store_Codes.csv') 
     #you should use extDataDir as the path to your file Store_Codes.csv file
 else:
     # we are running in a normal Python environment
     extDataDir = os.getcwd()
     extDataDir = os.path.join(extDataDir,another_folder 'Store_Codes.csv') 
     #you should use extDataDir as the path to your file Store_Codes.csv file

Upvotes: 6

Shane
Shane

Reputation: 2391

Well there's actually an easiest work around, rename your Store_Codes.csv into Store_Codes.py then edit the file:

csv_codes = """

csv file content...

"""

In your main script: import Store_Codes and then csv_file_content = Store_Codes.csv_codes.

Then in pyinstaller use --onefile, it'll automatically include Store_Codes.py into your newly generated exe file.

P.S. If it's utf-8 encoded content in the csv file, don't forget # -*- coding: utf-8 -*-

Upvotes: 0

Related Questions