Python, files con percorsi assoluti e relativi e come gestire l'accesso alle cartelle speciali

Autore:[Antonio Gallonetto]

Questo articolo descrive come utilizzare i percorsi per riuscire a scrivere o leggere un file in una cartella specifica o una sottocartella del nostro software, come accedere alle varie cartelle speciali, Desktop e Documenti, e come gestire i percorsi nei vari sistemi operativi, si trovano vari esempi di codice portabile.

Python percorsi relativi e assoluti

Un percorso di un file è assoluto quando è completamente indicato. Nel caso di Windows il percorso alla cartella utente potrebbe essere qualcosa del tipo: C:\Users\nomeUtente nel caso di Linux /home/nomeUtente e nel caso di Mac Os /Users/nomeUtente. Andiamo ad indicare il path completo dalla radice fino al nome del file che ci interessa.

Percorso relativo. E’ quel percorso che prende come punto di riferimento la cartella di lavoro corrente. Se si indica soltanto il nome del file questo si intende che sia contenuto nella directory corrente di lavoro altrimenti. Per i percorsi relativi esistono due cartelle virtuali indicate con un punto . e con due punti .. la prima indica quella corrente ed è necessaria se vogliamo proseguire con il nostro percorso verso il basso, mentre i due punti indicano la posizione precedente a quella corrente.

Un esempio di utilizzo di un percorso relativo in ambiente Linux potrebbe essere il seguente:

f = open('./prova/test.txt', "w",encoding='UTF-8') # apriamo il file in scrittura
f.write("Prova di lettura in un percorso relativo")
f.close()
f = open('./prova/test.txt', "r",encoding='UTF-8') 
print(f.read())
f.close()

In questo caso rispetto alla directory corrente andremo a scrivere il file test.txt nella sottodirectory prova e poi nella stessa andremo a leggere il file di testo.

Un esempio di percorso relativo andando in cartelle di livello superiore a quella corrente è:

f = open('../../python/test.txt', "w",encoding='UTF-8') # apriamo il file in scrittura
f.write("Prova di lettura in un percorso relativo")
f.close()
f = open('../../python/test.txt', "r",encoding='UTF-8') 
print(f.read())
f.close()

In questo caso andiamo su di due livelli nell’albero delle directory rispetto a quella corrente e poi entriamo nella cartella python e andiamo a scrivere e leggere il file test.txt.

Come posso sapere la directory corrente dove si trova il mio script python e creare un percorso da quel punto

La posizione del nostro programmino python la troviamo nella variabile __file__.

Per estrarre il percorso dobbiamo disturbare una libreria e qui abbiamo due possibilità o quella denominata os oppure pathlib, vediamo entrambe le soluzioni.

La soluzione con pathlib:

print(__file__)
p=Path(__file__)
print(p.parent.absolute())

Questo codice segue la seguente logica:

La soluzione con la libreria OS

print(__file__)
p=os.path.abspath(__file__)
print(p)
print(os.path.dirname(p) )

La logica di questo blocco di codice è la seguente:

Avere il percorso della nostra applicazione è particolarmente utile perchè poi possiamo impostarla come directory di lavoro.
Infatti la nostra directory corrente non è quella nella quale si trova il software ma quella dalla quale lo eseguiamo.
Se apro una shell da terminale, nei sistemi unix linux e simili, la cartella di lavoro è la home dell’utente. Eseguendo il software in questo modo: python3 ~/Desktop/script/prova.py, la mia cartella di lavoro rimane la home dell’utente.
I percorsi relativi e assoluti fino a questo punto non sono molto utili. Una cartella archivio nella directory dello script di esecuzione con dentro un database non ho modo di accedere all’archivio utilizzando percorsi assoluti e relativi ed essere sicuro che il mio codice sia portabile nei vari sistemi operativi. Se vado ad estrarmi il percorso dello script allora posso usare sia i percorsi relativi che assoluti per caricare il mio file. Per i percorsi relativi è necessario impostare come cartella di lavoro quella del percorso estratto, per i percorsi assoluti è necessario aggiungere al path la cartella archivio e poi il nome del file.

Esempio di file in una sottodirectory archivio con percorso relativo

import os
print(__file__)
p=Path(__file__)
percorso=p.parent.absolute()
os.chdir(percorso)
f = open('./archivio/test.txt', "r",encoding='UTF-8') 
print(f.read())
f.close()

In questo caso abbiamo il file test.txt nella sottocartella archivio del nostro programma. La logica del programma è estrarre il percorso del nostro software, impostare la nostra cartella di lavoro in quella posizione e a quel punto entriamo nella sottocartella archivio e leggiamo il file test.txt

Esempio di file in una sottodirectory archivio con percorso assoluto

print(__file__)
p=Path(__file__)
percorso=p.parent.absolute()
percorso=Path.joinpath(percorso, "archivio","test.txt")

##forma meno compatta della riga precedente
#percorso=Path.joinpath(percorso, "archivio","test.txt")
#percorso=Path.joinpath(percorso, "test.txt")

print("-----\n")
print(str(percorso)+"\n")
print("-----\n")
f = open(percorso, "r",encoding='UTF-8') 
print(f.read())
f.close()

In questo caso usiamo la funzione joinpath per creare il percorso assoluto al nostro file test.txt

Differenze nei vari sistemi operativi Windows, Macos e Linux

La libreria pathlib si occupa di gestire le differenze tra i vari sistemi operativi. I path se assoluti li andremo ad indicare utilizzando la convenzione per i sistemi unix quindi con le barre di questo tipo: “/”. La libreria poi si prenderà carico quando andiamo ad indicargli che è un path di gestire le differenze dei vari sistemi operativi.
La libreria non è in grado di gestire completamente le differenze tra Windows ed i sistemi unix-like, ad esempio rispetto alla lettera del disco, quindi se andiamo ad indicare Path("/Users/antonio) se andiamo a stampare questo percorso in Windows il percorso avrà l’indicazione corretta \Users\antonio ma manca il riferimento al drive di partenza.
Quindi per la portabilità del software la cosa migliore è estrarre il percorso al momento dell’esecuzione, quindi sarà relativo al sistema operativo che lo esegue e poi andremo a fare le varie operazioni su quello.

Cartelle speciali

Per cartelle speciali intendo il Desktop, Documenti oppure la cartella home dell’utente

Per accedere alla cartella home dell’utente possiamo usare un blocco di codice di questo tipo:

from pathlib import Path
myhome=Path.home()
print(myhome)

Per accedere alla cartella documenti:

from pathlib import Path
myhome=Path.home()
print(myhome)
pathdocumenti=Path.joinpath(myhome, "Documents")
print(pathdocumenti)

Nel caso nel quale la cartella documenti abbia un nome diverso da Documents il codice non funziona correttamente e sarà necessario perfezionare lo script in modo che si adatti ad una diversa mappatura.

Per la cartella Desktop è sufficiente cambiare “Documents” in “Desktop”