Pyinstaller App Is Accessing Txt Files, But Not Writing To Them (works Before App Compilation)
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)"