Ta fram platsen (sökvägen) för en fil som körs i Python: __file__.

Företag

Använd __file__ för att få fram platsen (sökvägen) för en pågående skriptfil i Python. Detta är användbart för att ladda andra filer baserat på platsen för den pågående filen.

Fram till Python 3.8 returnerar __file__ den sökväg som anges när du utför python-kommandot (eller python3-kommandot i vissa miljöer). Om en relativ sökväg anges returneras den relativa sökvägen; om en absolut sökväg anges returneras den absoluta sökvägen.

I Python 3.9 och senare returneras den absoluta sökvägen oavsett vilken sökväg som anges vid körning.

Följande innehåll förklaras.

  • os.getcwd(),__file__
  • Hämta filnamn och katalognamn för den fil som körs för tillfället.
  • Hämta den absoluta sökvägen till den fil som exekveras.
  • Läser andra filer baserat på platsen för den fil som körs för tillfället.
  • Flytta den aktuella katalogen till katalogen för den fil som körs.
  • Samma behandling kan utföras oavsett aktuell katalog vid körning.

I följande artikel finns information om hur du hämtar och ändrar den aktuella katalogen (arbetskatalogen).

Observera att __file__ inte kan användas i Jupyter Notebook (.ipynb).
Katalogen där .ipynb finns kommer att exekveras som den aktuella katalogen, oavsett i vilken katalog Jupyter Notebook startas.
Det är möjligt att använda os.chdir() i koden för att ändra den aktuella katalogen.

os.getcwd() och __file__.

I Windows kan du använda kommandot dir istället för pwd för att kontrollera den aktuella katalogen.

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

Skapa en Pythonskriptfil (file_path.py) med följande innehåll i den lägre nivån (data\src).

import os

print('getcwd:      ', os.getcwd())
print('__file__:    ', __file__)

Kör python-kommandot (eller python3-kommandot i vissa miljöer) och ange sökvägen till skriptfilen.

python3 data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     data/src/file_path.py

Den absoluta sökvägen till den aktuella katalogen kan fås med os.getcwd(). Du kan också använda __file__ för att få fram den sökväg som anges av python3-kommandot.

Fram till Python 3.8 innehåller __file__ den sökväg som anges i python-kommandot (eller python3-kommandot). I exemplet ovan returneras den relativa sökvägen eftersom den är relativ, men den absoluta sökvägen returneras om den är absolut.

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

Python 3.9 och senare returnerar den absoluta sökvägen till __file__, oavsett vilken sökväg som anges i kommandot python (eller python3).

I följande exempel lägger vi till koden i samma skriptfil (file_path.py) i Python 3.7 och kör den i förhållande till ovanstående katalog.

I Python 3.7 används den absoluta sökvägen. Resultaten visas i slutet av det här avsnittet.

Hämta filnamn och katalognamn för den fil som körs för tillfället.

För att få fram filnamnet och katalognamnet för den körda filen använder du följande funktion i modulen os.path i standardbiblioteket.

  • os.path.basename()
  • os.path.dirname()
print('basename:    ', os.path.basename(__file__))
print('dirname:     ', os.path.dirname(__file__))

Resultat av utförandet.

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

Hämta den absoluta sökvägen till den fil som exekveras.

Om en relativ sökväg erhålls med __file__ kan den konverteras till en absolut sökväg med os.path.abspath(). Kataloger kan också erhållas som absoluta sökvägar.

print('abspath:     ', os.path.abspath(__file__))
print('abs dirname: ', os.path.dirname(os.path.abspath(__file__)))

Resultat av utförandet.

# 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

Om en absolut sökväg anges i os.path.abspath() returneras den som den är. Om __file__ är en absolut sökväg kommer därför följande inte att orsaka något fel.

  • os.path.abspath(__file__)

Läser andra filer baserat på platsen för den fil som körs för tillfället.

Om du vill läsa andra filer baserat på platsen (sökvägen) för den fil som körs, sammanfogar du följande två filer med hjälp av os.path.join().

  • Katalog för den fil som körs
  • Relativ sökväg till den fil som ska läsas från den pågående filen.

Om du vill läsa en fil i samma katalog som den fil du kör är det bara att sätta ihop filnamnen.

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())

Resultat av utförandet.

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

Den övre nivån representeras av ”. \”. Du kan lämna den som den är, men du kan använda os.path.normpath() för att normalisera sökvägen och ta bort extra ”. \” och andra tecken.

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())

Resultat av utförandet.

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

Flytta den aktuella katalogen till katalogen för den fil som körs.

Använd os.chdir() för att flytta den aktuella katalogen till katalogen för den fil som körs i skriptet.

Du kan se att den flyttas av os.getcwd().

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

Resultat av utförandet.

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

När den aktuella katalogen har flyttats behöver du inte längre sammanfoga den med katalogen för den körda filen när du läser filen. Du kan bara ange sökvägen relativt till katalogen för den pågående filen.

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())

Resultat av utförandet.

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

Samma behandling kan utföras oavsett aktuell katalog vid körning.

Som vi har visat är det möjligt att läsa in filer baserat på platsen för skriptfilen, oberoende av den aktuella katalogen vid körning, med hjälp av en av följande metoder.

  • Sammanfoga katalogen för den pågående filen och den relativa sökvägen till den fil som ska läsas från den pågående filen med hjälp av os.path.join().
  • Flytta den aktuella katalogen till katalogen för den fil som körs.

Det är lättare att flytta den aktuella katalogen, men om du vill läsa eller skriva fler filer efter det måste du naturligtvis ta hänsyn till att den aktuella katalogen har flyttats.

Resultaten av de tidigare exemplen sammanfattas nedan.

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

Resultatet av att ange den absoluta sökvägen är följande.

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

Resultatet av att flytta den aktuella katalogen i terminalen och köra samma skriptfil visas nedan. Du kan se att samma fil kan läsas även om den exekveras från en annan plats.

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