Reputation: 726
Nuitka is good at compiling Python to excutable binary. But the compiled binary finds other resource files from original absolute path. Thus, for moving to another computer requires to make the directory tree same as the original one.
For example, if I compile a project like this:
/home/me/myproj/
╠═ myprog.py
╚═ resource
╚═ foo.data
I should put the resulting binary and resource to the same location of another computer. How to solve this problem?
My simpler spike is:
# /home/me/myproj/spike.py
import os
print(os.path.dirname(__file__))
And after compiling it, moving to any other location, I always got the result of /home/me/myproj
.
I need a result like /another/path
if I move compiled myproj.bin
to /another/path
.
Upvotes: 3
Views: 3543
Reputation: 558
For those who using nuitka with onefile mode, just use sys.executable
It will return something like /tmp/onefile_xxxxxxxx/python3
, and then you can os.path.dirname
it to get its parent dir
Upvotes: 0
Reputation: 294
here my working get relative path relative from nuitka frozen exe or the cwd when running single python file (python filename.py
).
import os
import sys
import re
from typing import Union
# Determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
__CWD__ = os.path.dirname(os.path.realpath(sys.executable))
elif __file__:
__CWD__ = os.getcwd()
def is_nuitka() -> bool:
"""
Check if the script is compiled with Nuitka.
"""
is_nuitka = "__compiled__" in globals()
is_nuitka2 = "NUITKA_ONEFILE_PARENT" in os.environ
return is_nuitka or is_nuitka2
def get_nuitka_file(filePath: str) -> str:
"""
Get the path for a file within a Nuitka compiled application.
Args:
filePath (str): The file path.
Returns:
str: The absolute file path.
"""
filePath = os.path.normpath(filePath)
is_nuitka_standalone = "__compiled__" in globals()
is_nuitka_onefile = "NUITKA_ONEFILE_PARENT" in os.environ
if is_nuitka_onefile:
temp_appd = os.path.join(os.getenv('localappdata'), 'Temp')
resdict = {}
for item in os.listdir(temp_appd):
if len(re.findall('''onefile_\d+_\d+''', item)) > 0:
resdict[re.findall('''onefile_\d+_(\d+)''', item)[0]] = item
respth = resdict[max(list(resdict.keys()))]
return os.path.join(os.getenv('localappdata'), 'Temp', respth, filePath)
if is_nuitka_standalone:
return os.path.join(__CWD__, filePath)
return os.path.normpath(os.path.join(__CWD__, filePath))
def get_relative_path(*args: Union[str, bytes]) -> str:
"""
Get the relative path from the current working directory (CWD).
Args:
*args (Union[str, bytes]): Variable number of path components.
Returns:
str: The normalized relative path.
"""
join_path = str(os.path.join(*args))
result = os.path.normpath(str(os.path.join(__CWD__, join_path)))
if is_nuitka():
result = os.path.normpath(str(os.path.join(os.path.dirname(sys.argv[0]), join_path)))
debug_log(os.path.dirname(sys.argv[0]), os.path.join(*args))
return result
Upvotes: 0
Reputation: 71
Try using sys.argv[0] with os.path.abspath instead of __file__
.
For example:
abs_pth = os.path.abspath(sys.argv[0])
your_dir = os.path.dirname(abs_pth)
for val in abs_pth,your_dir:
print(val)
This will help you get the current path to the executable binary file, as well as work with directories located in the same folder.
https://nuitka.net/doc/user-manual.html#onefile-finding-files
There is a difference between
sys.argv[0]
and__file__
of the main module for onefile more, that is caused by using a bootstrap to a temporary location. The first one will be the original executable path, where as the second one will be the temporary or permanent path the bootstrap executable unpacks to. Data files will be in the later location, your original environment files will be in the former location.
# This will find a file near your onefile.exe
open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt"))
# This will find a file inside your onefile.exe
open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt"))
Upvotes: 7
Reputation: 11
Another good function to resolve __file__
problem, it is to use --standalone
flag, which create one main ".bin" file + other ".so" dependencies in one folder.
python -m nuitka --standalone program.py
https://nuitka.net/doc/user-manual.html#use-case-4-program-distribution
Upvotes: 1