Get the path of the current file (script) in Python: __file__

Modified: | Tags: Python, File

In Python, you can use __file__ to get the path of the current file, i.e., the currently running script file (.py). This is particularly useful when you need to read other files relative to the current file's location.

In Python 3.8 and earlier, __file__ returns the path specified when executing the python (or python3) command. If you specify a relative path, it is returned as such, and the same applies for an absolute path.

From Python 3.9 onwards, however, __file__ always returns an absolute path, whether you used a relative or an absolute path when executing the python command.

In the sample code in this article, assume that you are working in the following directory. On Windows, you can check the current directory with the dir command instead of pwd.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

See the following article on how to get and change the current working directory in Python.

Note that __file__ is not available in Jupyter Notebook (.ipynb). Regardless of where you started the Jupyter Notebook, the current directory is where the .ipynb file is located. However, you can change the current directory by using os.chdir() in your code.

__file__ stores the path of the current script file

Create a Python script file (file_path.py) in the subdirectory (data/src).

import os

print('getcwd:      ', os.getcwd())
print('__file__:    ', __file__)
source: file_path.py

Execute this file with 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 get the absolute path of the current working directory using os.getcwd(), and you can obtain the path specified with the python3 command using __file__.

In Python 3.8 and earlier, __file__ stores the path specified when executing the python (or python3) command. In the above example, a relative path is specified, so it is returned; if specified as absolute, 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 stores an absolute path, regardless of whether the path specified with the python command is relative or absolute.

In the following examples, add code to the same script file (file_path.py) and execute it from the same directory as the above example, using Python 3.7.

Note that if __file__ is an absolute path (always the case with Python 3.9 or later, and when specifying the absolute path in Python 3.8 or earlier), you can use the same code below to read other files relative to the current script file location. The results of specifying the absolute path in Python 3.7 are shown at the end of this article.

Get the file and directory name of the current script file

You can use os.path.basename() and os.path.dirname() to get the file and directory name of the current script file.

import os

print('basename:    ', os.path.basename(__file__))
print('dirname:     ', os.path.dirname(__file__))
source: file_path.py

The result is as follows.

# basename:     file_path.py
# dirname:      data/src

If you want to get the name of the directory containing the current file (src in the example above), use os.path.basename(os.path.dirname(__file__)).

Get the absolute path of the current script file

If __file__ stores the 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__)))
source: file_path.py

The result 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 os.path.abspath() will simply return the same path if you give it an absolute path. So, even if __file__ is already an absolute path, using os.path.abspath(__file__) will not raise an error.

Read other files relative to the current file's location

If you want to read other files relative to the current file's location, you can use os.path.join() to combine the directory path of the current file and the relative path of the file you want to read.

If a file is in the same directory as the script file, you can read it by just specifying 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())
source: file_path.py

The result is as follows.

# [set target path 1]
# target_path_1:  data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!

In a file path, ../ represents the parent directory. Although the path will work as it is, you can use os.path.normpath() to normalize the path and eliminate any 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())
source: file_path.py

The result 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" !!

Refer to the following article for more information on reading files.

Change the current directory to the directory of the current script file

You can use os.chdir() to change the current working directory to the directory where the current script file is located.

You can then use os.getcwd() to confirm the change.

import os

print('[change directory]')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print('getcwd:      ', os.getcwd())
source: file_path.py

The result is as follows.

# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

If the current working directory is the same as the directory of the current file, you can use a relative path from the current file 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())
source: file_path.py

The result 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__ to obtain the path of the current script file, you can consistently read the same file, regardless of the current working directory.

As shown so far, there are two ways to do this:

  • Join the __file__ directory and the relative path (from __file__) of the file you want to read with os.path.join().
  • Change the current working directory to the __file__ directory.

While it is simpler to change the current directory, any subsequent file reading or writing operations should take into account that the current directory has been changed.

The results of the examples so far are as follows.

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" !!

The results when specifying the absolute path with the python3 command are as follows. As you can see, you can read the same file:

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" !!

Change the current directory in the terminal and execute the same script file, and you can see that the same file is read, even though the current directory is different.

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" !!

Related Categories

Related Articles