Introduzione
Quando si lavora con i file in Python, non basta sapere come aprirli o leggerli: spesso il vero problema è costruire, controllare e usare i percorsi in modo affidabile. Un percorso file scritto “a mano” può funzionare sul tuo computer e fallire su un altro sistema operativo, oppure diventare fragile quando cambia la struttura del progetto.
In questo tutorial vedremo un sotto-argomento molto utile e pratico: come gestire i percorsi dei file e verificare l’esistenza di file e cartelle usando pathlib, con un esempio reale orientato a un piccolo archivio di documenti. Questo approccio è fondamentale in script di automazione, tool da riga di comando, applicazioni backend e progetti data-oriented.
Il vantaggio di pathlib è semplice: rende il codice più leggibile, più robusto e più portabile rispetto alla manipolazione manuale di stringhe con slash e backslash.
Codice completo
from pathlib import Path
from datetime import datetime
def prepara_archivio(base_dir: Path) -> None:
"""
Crea la struttura minima dell´archivio:
- base_dir/
- base_dir/input/
- base_dir/output/
"""
input_dir = base_dir / "input"
output_dir = base_dir / "output"
input_dir.mkdir(parents=True, exist_ok=True)
output_dir.mkdir(parents=True, exist_ok=True)
def crea_file_di_esempio(input_dir: Path) -> Path:
"""
Crea un file di testo di esempio se non esiste già.
Restituisce il percorso del file creato o già presente.
"""
file_sorgente = input_dir / "documento.txt"
if not file_sorgente.exists():
contenuto = (
"Titolo: Report giornalieron"
"Data: 2026-07-02n"
"Stato: OKn"
)
file_sorgente.write_text(contenuto, encoding="utf-8")
return file_sorgente
def analizza_file(file_path: Path) -> dict:
"""
Legge un file di testo e restituisce informazioni utili:
- nome file
- estensione
- dimensione
- data di modifica
"""
if not file_path.exists():
raise FileNotFoundError(f"Il file non esiste: {file_path}")
if not file_path.is_file():
raise ValueError(f"Il percorso non punta a un file: {file_path}")
info = {
"nome": file_path.name,
"stem": file_path.stem,
"estensione": file_path.suffix,
"dimensione_byte": file_path.stat().st_size,
"modificato_il": datetime.fromtimestamp(file_path.stat().st_mtime),
"assoluto": file_path.resolve(),
}
return info
def copia_in_output(file_sorgente: Path, output_dir: Path) -> Path:
"""
Copia il file sorgente nella cartella output con un nome diverso.
"""
if not file_sorgente.exists():
raise FileNotFoundError(f"File sorgente mancante: {file_sorgente}")
output_dir.mkdir(parents=True, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
file_destinazione = output_dir / f"{file_sorgente.stem}_{timestamp}{file_sorgente.suffix}"
contenuto = file_sorgente.read_text(encoding="utf-8")
file_destinazione.write_text(contenuto, encoding="utf-8")
return file_destinazione
def lista_file_testo(cartella: Path) -> list[Path]:
"""
Elenca tutti i file .txt presenti in una cartella.
"""
if not cartella.exists():
raise FileNotFoundError(f"La cartella non esiste: {cartella}")
if not cartella.is_dir():
raise ValueError(f"Il percorso non è una cartella: {cartella}")
return [p for p in cartella.iterdir() if p.is_file() and p.suffix.lower() == ".txt"]
def main() -> None:
base_dir = Path("archivio_documenti")
prepara_archivio(base_dir)
input_dir = base_dir / "input"
output_dir = base_dir / "output"
file_sorgente = crea_file_di_esempio(input_dir)
info = analizza_file(file_sorgente)
print("Informazioni sul file:")
for chiave, valore in info.items():
print(f"- {chiave}: {valore}")
file_copiato = copia_in_output(file_sorgente, output_dir)
print(f"nFile copiato in: {file_copiato}")
print("nFile .txt presenti nella cartella input:")
for file_txt in lista_file_testo(input_dir):
print(f"- {file_txt.name}")
if __name__ == "__main__":
main() Spiegazione
Il cuore dell’esempio è pathlib.Path, una classe pensata per rappresentare i percorsi in modo oggettuale. Invece di concatenare stringhe come "cartella" + "/" + "file.txt", usiamo l’operatore / per costruire i percorsi:
base_dir / "input" / "documento.txt"
Questo stile è più leggibile e soprattutto portabile: Python si occupa di usare il separatore corretto su Windows, Linux e macOS.
1. Creazione delle cartelle
La funzione prepara_archivio() usa:
mkdir(parents=True, exist_ok=True)per creare anche le cartelle intermedie;exist_ok=Trueper evitare errori se la cartella esiste già.
Questa è una best practice importante negli script: rende il codice idempotente, cioè sicuro da rieseguire più volte.
2. Creazione di un file solo se assente
La funzione crea_file_di_esempio() controlla se documento.txt esiste già. Se non c’è, lo crea con write_text(). Questo evita di sovrascrivere accidentalmente dati già presenti.
Qui è fondamentale specificare encoding="utf-8", così il comportamento è coerente anche con caratteri accentati o simboli non ASCII.
3. Verifica del tipo di percorso
Prima di leggere informazioni sul file, analizza_file() controlla due aspetti:
exists(): il percorso esiste davvero?is_file(): il percorso punta a un file e non a una cartella?
Questi controlli evitano errori difficili da diagnosticare. Ad esempio, chiamare stat() su un percorso inesistente genera eccezioni inutili se non si valida prima l’input.
4. Estrazione dei metadati
Il metodo stat() permette di accedere a informazioni come:
- dimensione in byte con
st_size; - data di modifica con
st_mtime; - altri metadati utili per automazioni e controlli.
Nel codice convertiamo il timestamp in un oggetto datetime per renderlo leggibile.
5. Copia del file in una cartella di output
La funzione copia_in_output() mostra un caso molto comune: creare una copia del file con un nome nuovo, aggiungendo un timestamp. Questo è utile quando vuoi conservare versioni storiche o evitare collisioni di nome.
Il nuovo nome viene costruito in modo sicuro con:
file_sorgente.stem: nome senza estensione;file_sorgente.suffix: estensione;datetime.now().strftime(...): timestamp leggibile.
6. Filtrare i file per estensione
La funzione lista_file_testo() usa iterdir() per scorrere i contenuti di una cartella e selezionare solo i file con estensione .txt. Questo pattern è molto utile per elaborare batch di file, ad esempio report, esportazioni o input da pipeline automatiche.
Best practice
- Usa sempre
pathlibper i percorsi: evita concatenazioni manuali di stringhe. - Controlla sempre esistenza e tipo del percorso prima di leggere o scrivere.
- Imposta esplicitamente
encoding="utf-8"quando lavori con testi. - Preferisci
mkdir(parents=True, exist_ok=True)per creare cartelle in modo robusto. - Non sovrascrivere file senza una logica chiara: usa timestamp, backup o controlli preventivi.
- Usa nomi descrittivi per file e cartelle, specialmente nei progetti di automazione.
- Separa la logica di percorso dalla logica applicativa: funzioni piccole e focalizzate sono più facili da testare.
Riepilogo
Gestire bene i percorsi dei file è una competenza essenziale in Python. Con pathlib puoi costruire percorsi in modo leggibile, verificare l’esistenza di file e cartelle, leggere metadati e organizzare operazioni come copia e filtraggio in modo sicuro.
In questo tutorial hai visto un esempio pratico con un mini-archivio di documenti, ma gli stessi concetti si applicano a moltissimi scenari reali: importazione di dati, backup, esportazioni automatiche, script di manutenzione e tool da terminale.
Se vuoi scrivere codice solido, portabile e facile da mantenere, partire da una buona gestione dei percorsi è uno dei passi più importanti.
Approfondisci con risorse ufficiali
- Documentazione ufficiale di
pathlib:https://docs.python.org/3/library/pathlib.html - Documentazione ufficiale di
os.pathper confrontare l’approccio tradizionale:https://docs.python.org/3/library/os.path.html - Documentazione ufficiale di
datetime:https://docs.python.org/3/library/datetime.html - Guida alle I/O operations di Python:
https://docs.python.org/3/tutorial/inputoutput.html
