I have scripts calling other script files but I need to get the filepath of the file that is currently running within the process.
For example, let’s say I have three files. Using execfile:
How can I get the file name and path of
script_3.py, from code within
script_3.py, without having to pass that information as arguments from
os.getcwd() returns the original starting script’s filepath not the current file’s.)
It’s not entirely clear what you mean by “the filepath of the file that is currently running within the process”.
sys.argv usually contains the location of the script that was invoked by the Python interpreter.
Check the sys documentation for more details.
As @Tim and @Pat Notz have pointed out, the __file__ attribute provides access to
the file from which the module was
loaded, if it was loaded from a file
I think it’s just
__file__ Sounds like you may also want to checkout the inspect module.
__file__ attribute works for both the file containing the main execution code as well as imported modules.
import inspect, os print (inspect.getfile(inspect.currentframe())) # script filename (usually with path) print (os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # script directory
You can use
import inspect,os inspect.stack() => (<frame object at 0x00AC2AC0>, 'g:\Python\Test\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()n'], 0) os.path.abspath (inspect.stack()) => 'g:\Python\Test\_GetCurrentProgram.py'
as others have said. You may also want to use os.path.realpath to eliminate symlinks:
import os os.path.realpath(__file__)
import sys print sys.path
this would print the path of the currently executing script
The suggestions marked as best are all true if your script consists of only one file.
If you want to find out the name of the executable (i.e. the root file passed to the python interpreter for the current program) from a file that may be imported as a module, you need to do this (let’s assume this is in a file named foo.py):
Because the last thing (
[-1]) on the stack is the first thing that went into it (stacks are LIFO/FILO data structures).
Then in file bar.py if you
import foo it’ll print bar.py, rather than foo.py, which would be the value of all of these:
import sys print sys.argv
I used the approach with __file__
but there is a little trick, it returns the .py file
when the code is run the first time,
next runs give the name of *.pyc file
so I stayed with:
I think this is cleaner:
import inspect print inspect.stack()
and gets the same information as:
Where  is the current frame in the stack (top of stack) and  is for the file name, increase to go backwards in the stack i.e.
would be the file name of the script that called the current frame. Also, using [-1] will get you to the bottom of the stack, the original calling script.
I have a script that must work under windows environment.
This code snipped is what I’ve finished with:
import os,sys PROJECT_PATH = os.path.abspath(os.path.split(sys.argv))
it’s quite a hacky decision. But it requires no external libraries and it’s the most important thing in my case.
import os print os.path.basename(__file__)
this will give us the filename only. i.e. if abspath of file is c:abcdabc.py then 2nd line will print abc.py
import os os.path.dirname(os.path.abspath(__file__))
No need for inspect or any other library.
This worked for me when I had to import a script (from a different directory then the executed script), that used a configuration file residing in the same folder as the imported script.
import os os.path.dirname(__file__) # relative directory path os.path.abspath(__file__) # absolute file path os.path.basename(__file__) # the file name only
This should work:
import os,sys filename=os.path.basename(os.path.realpath(sys.argv)) dirname=os.path.dirname(os.path.realpath(sys.argv))
Here is a summary of experiments with Python 2 and 3. With
main.py – runs foo.py
foo.py – runs lib/bar.py
lib/bar.py – prints filepath expressions
| Python | Run statement | Filepath expression | |--------+---------------------+----------------------------------------| | 2 | execfile | os.path.abspath(inspect.stack()) | | 2 | from lib import bar | __file__ | | 3 | exec | (wasn't able to obtain it) | | 3 | import lib.bar | __file__ |
For Python 2, it might be clearer to switch to packages so can use
from lib import bar – just add empty
__init__.py files to the two folders.
For Python 3,
execfile doesn’t exist – the nearest alternative is
exec(open(<filename>).read()), though this affects the stack frames. It’s simplest to just use
import foo and
import lib.bar – no
__init__.py files needed.
Here is an experiment based on the answers in this thread – with Python 2.7.10 on Windows.
The stack-based ones are the only ones that seem to give reliable results. The last two have the shortest syntax, i.e. –
print os.path.abspath(inspect.stack()) # C:filepathslibbar.py print os.path.dirname(os.path.abspath(inspect.stack())) # C:filepathslib
Here’s to these being added to sys as functions! Credit to @Usagi and @pablog
Based on the following three files, and running main.py from its folder with
python main.py (also tried execfiles with absolute paths and calling from a separate folder).
import sys import os import inspect print "Python " + sys.version print print __file__ # main.py print sys.argv # main.py print inspect.stack() # lib/bar.py print sys.path # C:filepaths print print os.path.realpath(__file__) # C:filepathsmain.py print os.path.abspath(__file__) # C:filepathsmain.py print os.path.basename(__file__) # main.py print os.path.basename(os.path.realpath(sys.argv)) # main.py print print sys.path # C:filepaths print os.path.abspath(os.path.split(sys.argv)) # C:filepaths print os.path.dirname(os.path.abspath(__file__)) # C:filepaths print os.path.dirname(os.path.realpath(sys.argv)) # C:filepaths print os.path.dirname(__file__) # (empty string) print print inspect.getfile(inspect.currentframe()) # lib/bar.py print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:filepathslibbar.py print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:filepathslib print print os.path.abspath(inspect.stack()) # C:filepathslibbar.py print os.path.dirname(os.path.abspath(inspect.stack())) # C:filepathslib print
I wrote a function which take into account eclipse debugger and unittest.
It return the folder of the first script you launch. You can optionally specify the __file__ var, but the main thing is that you don’t have to share this variable across all your calling hierarchy.
Maybe you can handle others stack particular cases I didn’t see, but for me it’s ok.
import inspect, os def getRootDirectory(_file_=None): """ Get the directory of the root execution file Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing For eclipse user with unittest or debugger, the function search for the correct folder in the stack You can pass __file__ (with 4 underscores) if you want the caller directory """ # If we don't have the __file__ : if _file_ is None: # We get the last : rootFile = inspect.stack()[-1] folder = os.path.abspath(rootFile) # If we use unittest : if ("/pysrc" in folder) & ("org.python.pydev" in folder): previous = None # We search from left to right the case.py : for el in inspect.stack(): currentFile = os.path.abspath(el) if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile): break previous = currentFile folder = previous # We return the folder : return os.path.dirname(folder) else: # We return the folder according to specified __file__ : return os.path.dirname(os.path.realpath(_file_))
To get directory of executing script
print os.path.dirname( inspect.getfile(inspect.currentframe()))
Simplest way is:
import subprocess subprocess.call(['python3',<path_to_script_2.py>])
P.S.: I’ve tried
execfile, but since it reads script_2.py as a string,
import os os.path.dirname(os.path.realpath(__file__))
Here is what I use so I can throw my code anywhere without issue.
__name__ is always defined, but
__file__ is only defined when the code is run as a file (e.g. not in IDLE/iPython).
if '__file__' in globals(): self_name = globals()['__file__'] elif '__file__' in locals(): self_name = locals()['__file__'] else: self_name = __name__
Alternatively, this can be written as:
self_name = globals().get('__file__', locals().get('__file__', __name__))
Since Python 3 is fairly mainstream, I wanted to include a
pathlib answer, as I believe that it is probably now a better tool for accessing file and path information.
from pathlib import Path current_file: Path = Path(__file__).resolve()
If you are seeking the directory of the current file, it is as easy as adding
.parent to the
current_path: Path = Path(__file__).parent.resolve()
The following returns the path where your current main script is located at. I tested this with Linux, Win10, IPython and Jupyter Lab. I needed a solution that works for local Jupyter notebooks as well.
import builtins import os import sys def current_dir(): if "get_ipython" in globals() or "get_ipython" in dir(builtins): # os.getcwd() is PROBABLY the dir that hosts the active notebook script. # See also https://github.com/ipython/ipython/issues/10123 return os.getcwd() else: return os.path.abspath(os.path.dirname(sys.argv))