Het verkrijgen van de locatie (pad) van een lopend bestand in Python: __file__.

Bedrijf

Om de locatie (pad) van een lopend scriptbestand in Python te krijgen, gebruik je __file__. Dit is handig om andere bestanden te laden op basis van de locatie van het lopende bestand.

Tot Python 3.8 geeft __file__ het pad terug dat is opgegeven bij het uitvoeren van het python commando (of python3 commando in sommige omgevingen). Als een relatief pad is opgegeven, wordt het relatieve pad teruggegeven; als een absoluut pad is opgegeven, wordt het absolute pad teruggegeven.

In Python 3.9 en later wordt het absolute pad teruggegeven, ongeacht het pad dat tijdens runtime is opgegeven.

De volgende inhoud wordt toegelicht.

  • os.getcwd(),__file__
  • Verkrijg de bestandsnaam en de naam van de directory van het bestand dat momenteel wordt uitgevoerd.
  • Haal het absolute pad op van het bestand dat wordt uitgevoerd.
  • Leest andere bestanden op basis van de locatie van het bestand dat momenteel wordt uitgevoerd.
  • Verplaats de huidige directory naar de directory van het bestand dat wordt uitgevoerd.
  • Dezelfde verwerking kan worden gedaan ongeacht de huidige directory tijdens runtime.

Zie het volgende artikel voor informatie over het opvragen en wijzigen van de huidige directory (werkdirectory).

Merk op dat __file__ niet kan worden gebruikt in Jupyter Notebook (.ipynb).
De map waar .ipynb zich bevindt zal worden uitgevoerd als de huidige map, ongeacht de map waar Jupyter Notebook wordt gestart.
Het is mogelijk om os.chdir() in de code te gebruiken om de huidige directory te veranderen.

os.getcwd() en __file__.

In Windows kunt u het dir commando gebruiken in plaats van pwd om de huidige directory te controleren.

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

Maak een Python script bestand (file_path.py) met de volgende inhoud in het onderste niveau (data_rc).

import os

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

Voer het python commando uit (of python3 commando in sommige omgevingen) en specificeer het pad naar het scriptbestand.

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

Het absolute pad naar de huidige directory kan worden verkregen met os.getcwd(). U kunt ook __file__ gebruiken om het pad te krijgen dat door het python3 commando is opgegeven.

Tot Python 3.8 zal __file__ het pad bevatten dat in het python (of python3) commando is opgegeven. In het bovenstaande voorbeeld wordt het relatieve pad geretourneerd omdat het relatief is, maar het absolute pad wordt geretourneerd als het absoluut is.

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 en later geeft het absolute pad naar __file__, ongeacht het pad dat in de python (of python3) opdracht is opgegeven.

In het volgende voorbeeld zullen we de code toevoegen aan hetzelfde scriptbestand (file_path.py) in Python 3.7 en het uitvoeren relatief aan de bovenstaande directory.

In Python 3.7 wordt het absolute pad gebruikt. De resultaten worden getoond aan het einde van deze sectie.

Verkrijg de bestandsnaam en de naam van de directory van het bestand dat momenteel wordt uitgevoerd.

Om de bestandsnaam en de naam van de directory van het lopende bestand te krijgen, gebruikt u de volgende functie in de os.path module van de standaardbibliotheek.

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

Uitvoeringsresultaat.

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

Haal het absolute pad op van het bestand dat wordt uitgevoerd.

Als een relatief pad wordt verkregen met __file__, kan het worden geconverteerd naar een absoluut pad met os.path.abspath(). Directories kunnen ook worden verkregen als absolute paden.

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

Uitvoeringsresultaat.

# 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

Als een absoluut pad wordt opgegeven in os.path.abspath(), zal het worden geretourneerd zoals het is. Daarom, als __file__ een absoluut pad is, zal het volgende geen fout veroorzaken.

  • os.path.abspath(__file__)

Leest andere bestanden op basis van de locatie van het bestand dat momenteel wordt uitgevoerd.

Als je andere bestanden wilt lezen op basis van de locatie (het pad) van het bestand dat wordt uitgevoerd, voeg dan de volgende twee bestanden samen met os.path.join().

  • Directory van het bestand dat wordt uitgevoerd
  • Relatief pad naar het bestand dat moet worden gelezen uit het lopende bestand.

Als u een bestand wilt lezen in dezelfde directory als het bestand dat u uitvoert, hoeft u alleen maar de bestandsnaam aan elkaar te koppelen.

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

Uitvoeringsresultaat.

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

Het bovenste niveau wordt weergegeven door “. \”. U kunt het laten zoals het is, maar u kunt os.path.normpath() gebruiken om het pad te normaliseren en extra “. \en andere tekens te verwijderen.

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

Uitvoeringsresultaat.

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

Verplaats de huidige directory naar de directory van het bestand dat wordt uitgevoerd.

Gebruik os.chdir() om de huidige directory te verplaatsen naar de directory van het bestand dat in het script wordt uitgevoerd.

Je kunt zien dat het verplaatst wordt door os.getcwd().

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

Uitvoeringsresultaat.

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

Zodra de huidige directory is verplaatst, is het niet meer nodig deze te verbinden met de directory van het lopende bestand bij het lezen van het bestand. U kunt gewoon het pad opgeven relatief aan de directory van het lopende bestand.

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

Uitvoeringsresultaat.

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

Dezelfde verwerking kan worden gedaan ongeacht de huidige directory tijdens runtime.

Zoals we hebben laten zien, is het mogelijk om bestanden te laden op basis van de locatie van het scriptbestand, onafhankelijk van de huidige directory tijdens runtime, met behulp van een van de volgende methoden.

  • Voeg de directory van het lopende bestand samen met het relatieve pad naar het bestand dat uit het lopende bestand moet worden gelezen met os.path.join().
  • Verplaats de huidige directory naar de directory van het bestand dat wordt uitgevoerd.

Het is gemakkelijker om de huidige directory te verplaatsen, maar als je daarna nog meer bestanden wilt lezen of schrijven, moet je er natuurlijk wel rekening mee houden dat de huidige directory verplaatst is.

De resultaten van de voorgaande voorbeelden worden hieronder samengevat.

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

Het resultaat van het specificeren van het absolute pad is als volgt.

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

Het resultaat van het verplaatsen van de huidige directory in de terminal en het uitvoeren van hetzelfde scriptbestand is hieronder te zien. U kunt zien dat hetzelfde bestand kan worden gelezen, zelfs als het wordt uitgevoerd vanaf een andere locatie.

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