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:
- importo la libreria Path da pathlib
from pathlib import Path
- stampo il percorso del file del codice che sto eseguendo
print(__file__)
- associo a p l’oggetto Path in questo modo ho a disposizione le funzioni e gli attributi di un oggetto path
p=Path(__file__)
- a questo punto utilizzo la funzione
p.parent.absolute()
per estrarre il percorso del nostro file Se avessimo importato la libreria completa pathlib avremmo dovuto indicare ad esempio che la funzione Path è relativa alla libreria pathlib e quindi le chiamate sarebbero state di questo tipo: pathlib.Path(PERCORSO)
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:
- Importo la libreria OS
- Stampo il percorso del nostro script python
- associo all’oggetto p l’oggetto Path assoluto
- stampo p
- utilizzo la funzione dirname per estrarre il percorso del nostro script
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”