Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyInstaller cannot add .txt files

I'm fairly new with programming (and with Python) and the Stack Overflow question/response system allowed me to resolve all my problems until now. I didn't find any post directly addressing my current issue, but have to admit that I don't really know what's wrong. Let me explain.

I'm trying to make an executable file of a *.py script using PyInstaller. There's no problem doing it with a simple Python script (using --onefile), but it does not work when it comes to a more complex program that uses other *.py and *.txt files. I know that I need to modify the specification file and tried many alternatives - adding hidden files for instance.

Here are the files:

  • UpdatingStrategy.py (the target file to transform in executable)
  • LPRfunctions.py (UpdatingStrategy.py imports functions from this file)

The following *.txt files are read by UpdatingStrategy.py:

  • Strategy_Observ.txt
  • Strategy_Problems.txt
  • Updating_Observ1.txt
  • Updating_Observ2.txt
  • Updating_Problems.txt

I'm using Python 3.5 and Windows 10. Tell me if you need extra information.

How do I use the specification file properly and modify it in order to make an executable file of UpdatingStrategy.py?

I have read the PyInstaller documentation, but I lack many key principles and I couldn't make it work.

like image 845
PL de Chantal Avatar asked Oct 05 '16 23:10

PL de Chantal


2 Answers

After the line

a = Analysis( ... )

add

a.datas += [
    ("/absolute/path/to/some.txt","txt_files/some.txt","DATA"),
    ("/absolute/path/to/some2.txt","txt_files/some2.txt","DATA"),
    ("/absolute/path/to/some3.txt","txt_files/some3.txt","DATA"),
]

Then in your program use the following to get the resource path of your .txt files.

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.environ.get("_MEIPASS2",os.path.abspath("."))

    return os.path.join(base_path, relative_path)

 ...


 txt_data = open(resource_path("txt_files/some.txt")).read()

Make sure you build it like python -m PyInstaller my_target.spec ... do not call PyInstaller directly against your .py file after you have edited your specification file or it will overwrite your edited file...

like image 185
Joran Beasley Avatar answered Sep 22 '22 21:09

Joran Beasley


Anyone reading this in 2021... I've just run into similar issue with Pyinstaller. Needed to add a text file to my python code:

pyinstaller --add-data "/my/path/to/mytextfile.txt:/path/mytextfile.txt" mypython.py --onedir or --onefile

No matter if onedir or onefile, my code just never found the text file. Infact it threw the error:

IsADirectoryError: [Errno 21] Is a directory: /path/mytextfile.txt

Which didn't make sense to me because that's a file not a folder. Only when I checked this with the --onedir flag and I followed the path, I realized that pyinstaller would not only create a folder path, but also folder mytextfile.txt and put mytextfile.txt in there... so really the --add-data flag only wants a destination folder not the path to the file.

pyinstaller --add-data "/my/path/to/mytextfile.txt:path" mypython.py

or in the spec file i.e mypython.spec

datas=[('/my/path/to/mytextfile.txt', 'path')]

Should fix this. Note also the "DATA" configuration in the spec file is gone.

like image 24
lema Avatar answered Sep 25 '22 21:09

lema