Skip to content Skip to sidebar Skip to footer

Pyinstaller App Is Accessing Txt Files, But Not Writing To Them (works Before App Compilation)

settings.txt is stored and accessed within the compiled single file app, but it's not being written to. This works prior to Pyinstaller compilation when the file is in the same dir

Solution 1:

If you are on Windows, _MEIPASS returns the "short" name for the path in case that any component of it is more than 8 characters long. So, to test that this is the issue, try to make it a one-folder frozen app and then move it in a simple and short path: e.g., C:/test.

If this is the issue, you can workaround the problem by retrieving the long path using something like:

ifhasattr(sys, '_MEIPASS'):
    importwin32apisys_meipass= win32api.GetLongPathName(sys._MEIPASS)

Solution 2:

I wanted to share my solution, which simultaneously addresses many issues with relative paths in general (see function __doc__string).

I have a module named top_level_locator.py, with a modified function module_path as seen in other answers which takes a relative_path.

usage in other .py files:

from top_level_locator import module_path
resource_location = module_path(relative_path = 'resource.ext')

import sys
from pathlib import Path
from inspect import getsourcefile

defmodule_path(relative_path):
    """
    Combine top level path location, in this project app.py folder because it serves as main/entry_point, with user relative path.

    NOTE: top_level_locator.py should be in same folder as entry_point.py(/main.py) script 
    - TEST this with executable 
    - TEST this without executable 

    NOTE: care with use of __file__ as it comes with unwarranted side effects when:
    - running from IDLE (Python shell), no __file__ attribute
    - freezers, e.g. py2exe & pyinstaller do not have __file__ attribute! 

    NOTE: care with use of sys.argv[0]
    - unexpected result when you want current module path and get path where script/executable was run from! 

    NOTE: care with use of sys.executable
    - if non-frozen application/module/script: python/path/python.exe 
    - else                                   : standalone_application_executable_name.exe
    """# 0 if this module next to your_entry_point.py (main.py) else += 1 for every directory deeper
    n_deep = 1print('sys.executable:', sys.executable)
    print('   sys.argv[0]:', Path(sys.argv[0]).parents[n_deep].absolute() / sys.argv[0])
    print('      __file__:', __file__)
    print(' getsourcefile:', Path(getsourcefile(lambda:0)).parents[n_deep].absolute())
    
    ifhasattr(sys, "frozen"):
        # retreive possible longpath if needed from _MEIPASS: import win32api; # sys_meipass = win32api.GetLongPathName(sys._MEIPASS)
        base_path = getattr(sys, '_MEIPASS', Path(sys.executable).parent)
        print('      _MEIPASS:', base_path)
        return Path(base_path).joinpath(relative_path)
    return Path(getsourcefile(lambda:0)).parents[n_deep].absolute().joinpath(relative_path)

if __name__ == '__main__':
    module_path()

In non-frozen applications the output will (should) be as such:

  • sys.executable: C:\Users\<usr_name>\AppData\Local\Programs\Python\Python37\python.exe
  • sys.argv[0]: c:\Users\<usr_name>\Desktop\<project_name>\<project_code_folder>\app.py
  • __file__: c:\Users\<usr_name>\Desktop\<project_name>\<project_code_folder>\utils\top_level_locator.py
  • getsourcefile: c:\Users\<usr_name>\Desktop\<project_name>\<project_code_folder>

In frozen applications:

  • sys.executable: C:\Users\<usr_name>\Desktop\<project_name>\dist\app.exe
  • sys.argv[0]: C:\Users\<usr_name>\Desktop\<project_name>\dist\app.exe
  • __file__: C:\Users\<usr_name>\AppData\Local\Temp\_MEI155562\utils\top_level_locator.pyc
  • getsourcefile: C:\Users\<usr_name>\Desktop\<project_name>
  • _MEIPASS: C:\Users\<usr_name>\AppData\Local\Temp\_MEI155562

Post a Comment for "Pyinstaller App Is Accessing Txt Files, But Not Writing To Them (works Before App Compilation)"