Get the Path of the Current File (Script) in Python: __file__
In Python, you can use __file__
to get the path of the current script file (i.e., the .py
file being executed). This is particularly useful when you need to read other files relative to the location of the script.
In Python 3.8 and earlier, __file__
returns the path exactly as it was specified when you ran the script using the python
(or python3
) command. If you use a relative path, __file__
returns it as a relative path; if you use an absolute path, it returns an absolute path.
However, starting with Python 3.9, __file__
always returns an absolute path, regardless of whether you executed the script using a relative or absolute path.
__file__
stores the path of the current script file- Get the file name and directory of the current script file
- Get the absolute path of the current script file
- Read other files relative to the current file's location
- Change the working directory to the script's directory
- Read the same file regardless of the current working directory
In the sample code throughout this article, assume you are working in the following directory. On Windows, you can use the dir
command instead of pwd
to check the current directory.
pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook
For information on how to get and change the current working directory in Python, refer to the following article:
Note that __file__
is not available in Jupyter Notebook (.ipynb
). Regardless of where you launch the notebook, the working directory is set to the location of the .ipynb
file by default. However, you can change it within your code using os.chdir()
.
__file__
stores the path of the current script file
Create a Python script named file_path.py
in the data/src
subdirectory.
import os
print('getcwd: ', os.getcwd())
print('__file__: ', __file__)
Run this script using the python
(or python3
) command.
python3 data/src/file_path.py
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__: data/src/file_path.py
You can use os.getcwd()
to get the absolute path of the current working directory, and __file__
to get the path of the current script file.
In Python 3.8 and earlier, __file__
stores the path as given on the command line. In the example above, a relative path was used, so __file__
returns a relative path. If an absolute path were used instead, an absolute path would be returned.
pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook
python3 /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
In Python 3.9 and later, __file__
always returns an absolute path, regardless of how the script was executed.
In the following examples, add code to the same file_path.py
file and run it from the same directory as above, using Python 3.7.
Note that if __file__
is an absolute path (which is always the case in Python 3.9 and later, or when using an absolute path in earlier versions), you can use the same code shown below to access files relative to the script's location. At the end of this article, you’ll also see what happens when running the script with an absolute path in Python 3.7.
Get the file name and directory of the current script file
You can use os.path.basename()
and os.path.dirname()
to get the file name and the directory that contains the current script file.
import os
print('basename: ', os.path.basename(__file__))
print('dirname: ', os.path.dirname(__file__))
The output is as follows:
# basename: file_path.py
# dirname: data/src
To get only the name of the directory that contains the current script file (e.g., src
in this case), you can use os.path.basename(os.path.dirname(__file__))
.
Get the absolute path of the current script file
If __file__
is a relative path, you can convert it to an absolute path using os.path.abspath()
.
import os
print('abspath: ', os.path.abspath(__file__))
print('abs dirname: ', os.path.dirname(os.path.abspath(__file__)))
The output is as follows:
# abspath: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
Note that if __file__
is already an absolute path, os.path.abspath(__file__)
will simply return it as-is. No error is raised in either case.
Read other files relative to the current file's location
To read other files relative to the script's location, use os.path.join()
to combine the script’s directory path with the relative path to the target file.
If the file is in the same directory as the script file, you can simply pass its name.
import os
print('[set target path 1]')
target_path_1 = os.path.join(os.path.dirname(__file__), 'target_1.txt')
print('target_path_1: ', target_path_1)
print('read target file:')
with open(target_path_1) as f:
print(f.read())
The output is as follows:
# [set target path 1]
# target_path_1: data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
In file paths, ../
refers to the parent directory. Although such paths work, you can clean them up using os.path.normpath()
to eliminate unnecessary segments.
print('[set target path 2]')
target_path_2 = os.path.join(os.path.dirname(__file__), '../dst/target_2.txt')
print('target_path_2: ', target_path_2)
print('normalize : ', os.path.normpath(target_path_2))
print('read target file:')
with open(target_path_2) as f:
print(f.read())
The output is as follows:
# [set target path 2]
# target_path_2: data/src/../dst/target_2.txt
# normalize : data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
For more details on reading files in Python, refer to the following article:
Change the working directory to the script's directory
You can use os.chdir()
to change the current working directory to the directory where the current script file is located.
After changing the directory, you can confirm it using os.getcwd()
.
import os
print('[change directory]')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print('getcwd: ', os.getcwd())
The output is as follows:
# [change directory]
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
If your working directory is the same as the script’s directory, you can use relative paths from the script to read other files.
print('[set target path 1 (after chdir)]')
target_path_1 = 'target_1.txt'
print('target_path_1: ', target_path_1)
print('read target file:')
with open(target_path_1) as f:
print(f.read())
print()
print('[set target path 2 (after chdir)]')
target_path_2 = '../dst/target_2.txt'
print('target_path_2: ', target_path_2)
print('read target file:')
with open(target_path_2) as f:
print(f.read())
The output is as follows:
# [set target path 1 (after chdir)]
# target_path_1: target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2 (after chdir)]
# target_path_2: ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
Read the same file regardless of the current working directory
By using __file__
, you can reliably read the same file regardless of the current working directory.
As demonstrated above, there are two common approaches:
- Join the
__file__
directory with the file’s relative path usingos.path.join()
. - Change the current working directory to the
__file__
directory.
While changing the current directory is simpler, keep in mind that all subsequent file operations will be affected by the new working directory.
Here are the results from the examples so far:
pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook
python3 data/src/file_path.py
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__: data/src/file_path.py
# basename: file_path.py
# dirname: data/src
# abspath: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
#
# [set target path 1]
# target_path_1: data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2]
# target_path_2: data/src/../dst/target_2.txt
# normalize : data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
#
# [change directory]
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
#
# [set target path 1 (after chdir)]
# target_path_1: target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2 (after chdir)]
# target_path_2: ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
And here are the results when running the script with an absolute path using the python3
command. As shown, the same file can still be read:
pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook
python3 /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# basename: file_path.py
# dirname: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# abspath: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
#
# [set target path 1]
# target_path_1: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2]
# target_path_2: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/../dst/target_2.txt
# normalize : /Users/mbp/Documents/my-project/python-snippets/notebook/data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
#
# [change directory]
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
#
# [set target path 1 (after chdir)]
# target_path_1: target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2 (after chdir)]
# target_path_2: ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
Even if you change the working directory in the terminal before running the script, it will still read the same file:
cd data/src
pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
python3 file_path.py
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# __file__: file_path.py
# basename: file_path.py
# dirname:
# abspath: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
#
# [set target path 1]
# target_path_1: target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2]
# target_path_2: ../dst/target_2.txt
# normalize : ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
#
# [change directory]
# getcwd: /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
#
# [set target path 1 (after chdir)]
# target_path_1: target_1.txt
# read target file:
# !! This is "target_1.txt" !!
#
# [set target path 2 (after chdir)]
# target_path_2: ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!