2

I'm compiling a python application using pyinstaller.

The structure is like so -

d:\app\myprog.exe
d:\app\config\settings.conf

If I run myprog.exe --switch value from d:\app it runs fine, if I try to run from anywhere else like c:\windows it's not finding my settings.conf file complaining with the message:

Traceback (most recent call last):
  File "<string>", line 284, in <module>
  File "<string>", line 218, in main
  File "ConfigParser.py", line 330, in get
ConfigParser.NoSectionError: No section: 'database'
myApp returned -1

database being the first line in the config file I'm trying to reference.

I'm referencing the BASE_DIR from the app here -

# Global Path and Config Info
try:
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
except NameError:  # We are the main py2exe script, not a module
    BASE_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))

So that I can get the config file like this -

config = RawConfigParser()
config.read(os.path.join(BASE_DIR, 'config/settings.conf'))

But I guess BASE_DIR is whatever folder I'm running the EXE from (like c:\windows, not the location of the EXE (which is d:\app)?

whoisearth
  • 4,080
  • 13
  • 62
  • 130
  • 1
    I think this reduces to a duplicate of [this question](http://stackoverflow.com/a/404750/353839). See also the [pyinstaller](http://pythonhosted.org/PyInstaller/#using-file-and-sys-meipass) and [cx_Freeze](http://cx-freeze.readthedocs.org/en/latest/faq.html#using-data-files) docs. – bbayles Apr 19 '16 at 03:01

1 Answers1

6

As mentioned in PyInstaller documentation (in How the One-File Program Works section) when a single executable file (created by PyInstaller) is executed, what happens is that a directory structure of the required library modules (Python VM, libraries and packages, etc.) are extracted from that single executable to a temporary directory, and then the application is started from there.

This means that __file__ in your Python code is not going to be the path to the single executable file, and that's the reason for this issue.

I'd write my app to accept the path to the configuration file from command line arguments, fall back to using an environment variable if available, and then a hard coded default value based on the platform (as most multi platform applications do to reach to their configurations).

Another approach is to use the one-directory output from PyInstaller and include the configuration file in the same directory. Then to help make it easier to distribute the software to end users, use another tool to create a single Windows installer file from that directory structure. This way you'll be distributing the Windows installer, so users can run to install the application. But when the app runs, it runs from the directory where the configuration file resides.

farzad
  • 8,775
  • 6
  • 32
  • 41