How do you properly determine the current script directory?
is indeed the best you're going to get.
It's unusual to be executing a script with
execfile; normally you should be using the module infrastructure to load scripts. If you must use these methods, I suggest setting
__file__ in the
globals 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.
If you really want to cover the case that a script is called via
execfile(...), you can use the
inspect module to deduce the filename (including the path). As far as I am aware, this will work for all cases you listed:
filename = inspect.getframeinfo(inspect.currentframe()).filenamepath = os.path.dirname(os.path.abspath(filename))
#!/usr/bin/env pythonimport inspectimport osimport sysdef get_script_dir(follow_symlinks=True): if getattr(sys, 'frozen', False): # py2exe, PyInstaller, cx_Freeze path = os.path.abspath(sys.executable) else: path = inspect.getabsfile(get_script_dir) if follow_symlinks: path = os.path.realpath(path) return os.path.dirname(path)print(get_script_dir())
It works on CPython, Jython, Pypy. It works if the script is executed using
__file__ -based solutions would fail here). It works if the script is inside an executable zip file (/an egg). It works if the script is "imported" (
PYTHONPATH=/path/to/library.zip python -mscript_to_run) from a zip file; it returns the archive path in this case. It works if the script is compiled into a standalone executable (
sys.frozen). It works for symlinks (
realpath eliminates symbolic links). It works in an interactive interpreter; it returns the current working directory in this case.