I would like to see what is best way to determine current script directory in python?
I discovered that two to the many ways of calling python code, it is hard to find a good solution.
Here are some problems:
__file__
is not defined if the script is executed withexec
,execfile
__module__
is defined only in modules
Use cases:
./myfile.py
python myfile.py
./somedir/myfile.py
python somedir/myfile.py
execfile('myfile.py')
(from another script, that can be located in another directory and that can have another current directory.
I know that there is no perfect solution, because in some cases but I'm looking for the best approach that solved most of the cases.
The most used approach is os.path.dirname(os.path.abspath(__file__))
but this really doesn't work if you execute the script from another one with exec()
.
Warning
Any solution that uses current directory will fail, this can be different based on the way the script is called or it can be changed inside the running script.
In Python 3.4+ you can use the simpler
pathlib
module:Just use
os.path.dirname(os.path.abspath(__file__))
and examine very carefully whether there is a real need for the case whereexec
is used. It could be a sign of troubled design if you are not able to use your script as a module.Keep in mind Zen of Python #8, and if you believe there is a good argument for a use-case where it must work for
exec
, then please let us know some more details about the background of the problem.is indeed the best you're going to get.
It's unusual to be executing a script with
exec
/execfile
; normally you should be using the module infrastructure to load scripts. If you must use these methods, I suggest setting__file__
in theglobals
you pass to the script so it can read that filename.There's no other way to get the filename in execed code: as you note, the CWD may be in a completely different place.
just
pwd
at jupyter notebook :
pwd
+ shift + enterat spyder :
pwd
+ F9If you really want to cover the case that a script is called via
execfile(...)
, you can use theinspect
module to deduce the filename (including the path). As far as I am aware, this will work for all cases you listed:Here is a partial solution, still better than all published ones so far.
Now this works will all calls but if someone use
chdir()
to change the current directory, this will also fail.Notes:
sys.argv[0]
is not going to work, will return-c
if you execute the script withpython -c "execfile('path-tester.py')"