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:
script_1.pycallsscript_2.py.- In turn,
script_2.pycallsscript_3.py.
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 script_2.py?
(Executing os.getcwd() returns the original starting script’s filepath not the current file’s.)
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
__file__
as others have said. You may also want to use os.path.realpath to eliminate symlinks:
import os os.path.realpath(__file__)
Method 2
p1.py:
execfile("p2.py")
p2.py:
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
Method 3
Update 2018-11-28:
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()[0][1]) |
| 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.
See also Difference between import and execfile
Original Answer:
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()[0][1]) # C:filepathslibbar.py print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # 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).
C:filepathsmain.py: execfile('foo.py')
C:filepathsfoo.py: execfile('lib/bar.py')
C:filepathslibbar.py:
import sys import os import inspect print "Python " + sys.version print print __file__ # main.py print sys.argv[0] # main.py print inspect.stack()[0][1] # lib/bar.py print sys.path[0] # 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[0])) # main.py print print sys.path[0] # C:filepaths print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:filepaths print os.path.dirname(os.path.abspath(__file__)) # C:filepaths print os.path.dirname(os.path.realpath(sys.argv[0])) # 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()[0][1]) # C:filepathslibbar.py print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:filepathslib print
Method 4
I think this is cleaner:
import inspect print inspect.stack()[0][1]
and gets the same information as:
print inspect.getfile(inspect.currentframe())
Where [0] is the current frame in the stack (top of stack) and [1] is for the file name, increase to go backwards in the stack i.e.
print inspect.stack()[1][1]
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.
Method 5
import os os.path.dirname(__file__) # relative directory path os.path.abspath(__file__) # absolute file path os.path.basename(__file__) # the file name only
Method 6
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):
import inspect
print inspect.stack()[-1][1]
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:
__file__inspect.getfile(inspect.currentframe())inspect.stack()[0][1]
Method 7
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 Path() statement:
current_path: Path = Path(__file__).parent.resolve()
Method 8
It’s not entirely clear what you mean by “the filepath of the file that is currently running within the process”.
sys.argv[0] 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
Method 9
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
Method 10
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[0])[0])
it’s quite a hacky decision. But it requires no external libraries and it’s the most important thing in my case.
Method 11
Try this,
import os os.path.dirname(os.path.realpath(__file__))
Method 12
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.
Method 13
The __file__ attribute works for both the file containing the main execution code as well as imported modules.
See https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
Method 14
import sys print sys.path[0]
this would print the path of the currently executing script
Method 15
I think it’s just __file__ Sounds like you may also want to checkout the inspect module.
Method 16
You can use inspect.stack()
import inspect,os inspect.stack()[0] => (<frame object at 0x00AC2AC0>, 'g:\Python\Test\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]n'], 0) os.path.abspath (inspect.stack()[0][1]) => 'g:\Python\Test\_GetCurrentProgram.py'
Method 17
import sys print sys.argv[0]
Method 18
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
Method 19
This should work:
import os,sys filename=os.path.basename(os.path.realpath(sys.argv[0])) dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Method 20
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__))
Method 21
To get directory of executing script
print os.path.dirname( inspect.getfile(inspect.currentframe()))
Method 22
I used the approach with __file__
os.path.abspath(__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:
inspect.getfile(inspect.currentframe())
or
sys._getframe().f_code.co_filename
Method 23
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][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[1])
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_))
Method 24
To keep the migration consistency across platforms (macOS/Windows/Linux), try:
path = r'%s' % os.getcwd().replace('\','/')
Method 25
Simplest way is:
in script_1.py:
import subprocess subprocess.call(['python3',<path_to_script_2.py>])
in script_2.py:
sys.argv[0]
P.S.: I’ve tried execfile, but since it reads script_2.py as a string, sys.argv[0] returned <string>.
Method 26
I have always just used the os feature of Current Working Directory, or CWD. This is part of the standard library, and is very easy to implement.
Here is an example:
import os
base_directory = os.getcwd()
Method 27
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[0]))
Method 28
if you want just the filename without ./ or .py you can try this
filename = testscript.py file_name = __file__[2:-3]
file_name will print testscript
you can generate whatever you want by changing the index inside []
Method 29
import os import wx # return the full path of this file print(os.getcwd()) icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16) # put the icon on the frame self.SetIcon(icon)
Method 30
Most of these answers were written in Python version 2.x or earlier. In Python 3.x the syntax for the print function has changed to require parentheses, i.e. print().
So, this earlier high score answer from user13993 in Python 2.x:
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
Becomes in Python 3.x:
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
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0