get the path of the executed file once "compiled" with pyinstaller - python

I know there are a lot of answers on this subject, but no one works once you compile a script in an executable.
In my python script, I create a file within the same directory of the script.
to get the path of the current dir I use pathlib
basepath = Path(__file__).parent
filename='myfile'
filepath=os.path.join(basepath, filename)
if I print the directory I get the file wrote in the good directory and everything works fine within python
(i.e desktop/myname/myscriptdir/myfile)
but once I "compile" with pyinstaller with --onefile, if I launch the executable, the directory will be
like
/var/folders/nr/w0698dl96j39_fq33lqd8pk80000gn/T/_MEIP12KxC/myfile
believed me, I tried a lot of various method (abspath, os.realpath..)to get the current dir, no one worked fine once in an executable file.

When you compile an app using pyinstaller with the --onefile or -F flag, the file that it creates is actually an archive file, like a .zip file.
When you execute that file it launches a process that extracts itself into a temporary folder somewhere in your OS filesystem. This is the path that is reported when you use the __file__ variable in the compiled application.
It then continues to launch your application from there and the temporary directory becomes the runtime durectory for the duration of the apps life. When the app is finally closed it deletes the temporary runtime directory on it's way out.
Since this is the case there are alternatives.
To get the current working directory during runtime use:
path = '.'
#or
path = os.getcwd()
To get the path to the compiled executable file during runtime:
path = sys.executable

Related

Using __file__ in script to get current file directory of script and executable file

I'm trying to write universal scripts that would work on any PC that meets requirements and I have a little problem with getting directories and paths right. Currently I have two folders in one location: C:\Users\myProject, one with my Scripts and other named Tests. In Scripts folder I store my python scripts with all instructions and in Tests I have .bat files used to execute scripts. To get parents path I decided to use (__file__), for example in my script - Test_Script.py:
__file__ = 'Test_Script.py'
print(r'__file__', __file__)
curr_path = os.path.dirname(os.path.abspath(__file__))
print (curr_path)
And it works, but in two ways. If I run cmd in folder with Scripts and type: py Test_Script.py, I get:
Test_Script.py
C:\Users\myProject\Scripts
But when I run it from Tests directory, I get:
Test_Script.py
C:\Windows\system32
How do I fix this to have same output as in first case while running script via cmd?

python change default directory

so I recently tried using playsound and the .mp3 is in the same folder as the .py, and it says it could not find the file.
I printed out the current directory and it says it's at C:\Users\me
Shouldn't this be at the same directory as where the .py script is at? This has been happening with my other python scripts where I have to explicitly give it the directory, whereas before I didn't have to and it was just where the python script was at.
Is there a setting for this?
The current directory is defined by where you execute the python file not the location of it. If you want to change the directory you can use the os module:
import os
os.chdir(PATH)
If you're looking for a file in the same directory as the executing python program:
basename = os.path.basename(__file__)
my_file_name = basename + "/myfile"
with open(my_file_name) as my_file:
...
The variable __file__ contains the full pathname of the currently executing Python program.

Python-Pyinstaller -- can not get the file path properly when ran from a different directory after being converted to .exe

I am trying to print the directory of the .py file however I want to run the file from another directory by adding the file's directory to the system Path file. I ran in to some problems when I turned to file to an executable with pyinstaller.
The code in the file:
import pathlib
path= pathlib.Path(__file__).parent.resolve()
print(path)
Let's say the directory of the file is: C:\Users\User\Documents\file.py
And let's say the current working directory is: C:\Users\User
When I run file.py I get:
C:\Users\User\Documents
which is the output I want
When I run file.exe I get:
C:\Users\User
which is not what I wan't
I don't understand why the .py and .exe files are working differently.
What can I do to fix the problem?
I tried a bunch of stuff from here but none of them seem to work:
How do I get the full path of the current file's directory?

Setting working directory of a converted .py file to .exe file

I am having issues with a converted .exe file. It does not find my excel file.
I have the following code
import pandas as pd
import os
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
#Load data
data = pd.read_excel("data.xlsx")
...
The second part of the code (abspath, dname, os.chdir(dname) is setting the path to the location of the .py file. Hence, having the .py file and .xlsx file together will always make it find it no matter the location.
Then I convert it to .exe using
pyinstaller --hidden-import=pandas --onefile script.py
To make my script.py work, I have to have the data.xlsx file in the same folder as the script.py file.
I would assume dragging the .exe file out of the dir folder into the same location at as the .xlsx file would make it run but running the .exe files returns the following error:
Failed to execute script script. No such file 'data.xlsx' in directory.
How can I make it read my excel file no matter the location of the '.exe+.xlsx' folder?
The problem you're encountering is that when you run the executable the files are extracted to a temporary directory and run from there. This means that i) the current/working directory is the temporary directory and ii) the location of the program that is actually executing is also that temporary directory, so neither way of obtaining the path will do what you want.
However, when run as an executable some additional values are available via the sys module. The ones that are useful in this case are sys.frozen, which is set to True, and sys.executable, which is set to the location of the executable that the user ran.
In the past I've found the path I need in the following way:
if getattr(sys, 'frozen', False):
app_path = os.path.dirname(sys.executable)
else:
app_path = os.path.dirname(os.path.abspath(__file__))
where app_path will now be the directory of the script or executable. You can then use this as the basis of accessing other files.

Script writes file in wrong directory

I just experienced a weird behaviour in Python.
I created a copy of a script.py file in a sub-folder within the folder that contains the initial script.
The script at the end exports some data into a .txt file by using:
with open('clayList.2203.txt', 'w',encoding='utf-8') as f:
for item in claysUniqueList:
f.write("%s\n" % item)
The problem is that Python writes the new file on the parent directory instead of the current one.
I checked the path with:
print(sys.path[0])
and it prints the current path correctly.
By default, relative paths are relative to the working directory, that is the directory from which is run the command that run the script.
If you want the path to be relative from the script directory, you will have to explicitly code this behaviour:
import os
filepath = os.path.join(os.path.dirname(__file__), 'clayList.2203.txt')
with open(filepath, 'w',encoding='utf-8') as f:
# ...
When you run code in Visual Studio, there are debugging options.
One of these it the directory to run from, called "Working directory".
(Right click your project and go to settings).
To run from the sub-directory you need to change this.
If you want to start in a sub directory, type that in instead, in the "working directory" shown here:
path for creating the file should be relative to the directory of execution
e.g. your pwd is parent and your script is in parent/child1/child2/script.py then path of the file to be created should be ./child1/child2/clayList.2203.txt

Categories