Ottenere la posizione (percorso) di un file in esecuzione in Python: __file__.

Attività commerciale

Per ottenere la posizione (percorso) di un file di script in esecuzione in Python, usate __file__. Questo è utile per caricare altri file in base alla posizione del file in esecuzione.

Fino a Python 3.8, __file__ restituisce il percorso specificato durante l'esecuzione del comando python (o comando python3 in alcuni ambienti). Se viene specificato un percorso relativo, viene restituito il percorso relativo; se viene specificato un percorso assoluto, viene restituito il percorso assoluto.

In Python 3.9 e successivi, il percorso assoluto viene restituito indipendentemente dal percorso specificato a runtime.

Vengono spiegati i seguenti contenuti.

  • os.getcwd(),__file__
  • Ottiene il nome del file e della directory del file attualmente in esecuzione.
  • Ottiene il percorso assoluto del file in esecuzione.
  • Legge altri file in base alla posizione del file in esecuzione.
  • Sposta la directory corrente nella directory del file in esecuzione.
  • La stessa elaborazione può essere fatta indipendentemente dalla directory corrente in fase di esecuzione.

Vedi il seguente articolo per informazioni su come ottenere e cambiare la directory corrente (directory di lavoro).

Si noti che __file__ non può essere usato in Jupyter Notebook (.ipynb).
La directory in cui si trova .ipynb sarà eseguita come directory corrente, indipendentemente dalla directory in cui Jupyter Notebook è avviato.
È possibile usare os.chdir() nel codice per cambiare la directory corrente.

os.getcwd() e __file__.

In Windows, potete usare il comando dir invece di pwd per controllare la directory corrente.

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

Create un file di script Python (file_path.py) con il seguente contenuto nel livello inferiore (data\src).

import os

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

Eseguite il comando python (o il comando python3 in alcuni ambienti) specificando il percorso del file di script.

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

Il percorso assoluto della directory corrente può essere ottenuto con os.getcwd(). Potete anche usare __file__ per ottenere il percorso specificato dal comando python3.

Fino a Python 3.8, __file__ conterrà il percorso specificato nel comando python (o python3). Nell'esempio sopra, il percorso relativo viene restituito perché è relativo, ma il percorso assoluto viene restituito se è assoluto.

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 e successivi restituisce il percorso assoluto a __file__, indipendentemente dal percorso specificato nel comando python (o python3).

Nell'esempio seguente, aggiungeremo il codice allo stesso file di script (file_path.py) in Python 3.7 e lo eseguiremo relativo alla directory di cui sopra.

In Python 3.7, viene usato il percorso assoluto. I risultati sono mostrati alla fine di questa sezione.

Ottiene il nome del file e della directory del file attualmente in esecuzione.

Per ottenere il nome del file e della directory del file in esecuzione, usate la seguente funzione nel modulo os.path della libreria standard.

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

Risultato dell'esecuzione.

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

Ottiene il percorso assoluto del file in esecuzione.

Se un percorso relativo è ottenuto con __file__, può essere convertito in un percorso assoluto con os.path.abspath(). Anche le directory possono essere ottenute come percorsi assoluti.

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

Risultato dell'esecuzione.

# 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

Se un percorso assoluto è specificato in os.path.abspath(), sarà restituito così com'è. Pertanto, se __file__ è un percorso assoluto, quanto segue non causerà un errore.

  • os.path.abspath(__file__)

Legge altri file in base alla posizione del file in esecuzione.

Se volete leggere altri file in base alla posizione (percorso) del file in esecuzione, unite i seguenti due file usando os.path.join().

  • Directory del file in esecuzione
  • Percorso relativo al file da leggere dal file in esecuzione.

Se volete leggere un file nella stessa directory del file che state eseguendo, basta concatenare il nome del file.

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

Risultato dell'esecuzione.

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

Il livello superiore è rappresentato da “. \”. Potete lasciarlo così com'è, ma potete usare os.path.normpath() per normalizzare il percorso e rimuovere gli extra “. \” e altri caratteri.

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

Risultato dell'esecuzione.

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

Sposta la directory corrente nella directory del file in esecuzione.

Usate os.chdir() per spostare la directory corrente nella directory del file che viene eseguito nello script.

Potete vedere che è spostato da os.getcwd().

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

Risultato dell'esecuzione.

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

Una volta che la directory corrente è stata spostata, non c'è bisogno di concatenarla con la directory del file in esecuzione quando si legge il file. Potete semplicemente specificare il percorso relativo alla directory del file in esecuzione.

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

Risultato dell'esecuzione.

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

La stessa elaborazione può essere fatta indipendentemente dalla directory corrente in fase di esecuzione.

Come abbiamo mostrato, è possibile caricare i file in base alla posizione del file di script, indipendentemente dalla directory corrente in fase di esecuzione, utilizzando uno dei seguenti metodi.

  • Concatena la directory del file in esecuzione e il percorso relativo al file da leggere dal file in esecuzione usando os.path.join().
  • Sposta la directory corrente nella directory del file in esecuzione.

È più facile spostare la directory corrente, ma naturalmente, se volete leggere o scrivere altri file dopo, dovete tenere conto che la directory corrente è stata spostata.

I risultati degli esempi precedenti sono riassunti di seguito.

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

Il risultato di specificare il percorso assoluto è il seguente.

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

Il risultato dello spostamento della directory corrente nel terminale e dell'esecuzione dello stesso file di script è mostrato qui sotto. Potete vedere che lo stesso file può essere letto anche se viene eseguito da una posizione diversa.

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

Copied title and URL