← Tutte le guide

Python: `pathlib` al posto di `os.path`, con le differenze che contano

27 ottobre 2026 · 2 min di lettura

pathlib tratta i percorsi come oggetti invece che come stringhe. Il codice è più leggibile; in cambio costa un po' di tempo, e conviene sapere dove.

Le equivalenze che usi ogni giorno

import os
from pathlib import Path

p = Path("/dati") / "sub" / "a.txt"

os.path.join("/dati", "sub", "a.txt")   # p
os.path.basename(p)                      # p.name        -> "a.txt"
os.path.dirname(p)                       # p.parent
os.path.splitext(p)[1]                   # p.suffix      -> ".txt"
p.stem                                   # "a"
p.with_suffix(".md")                     # /dati/sub/a.md
p.relative_to("/dati")                   # sub/a.txt
p.relative_to("/dati").parts             # ('sub', 'a.txt')

Ho verificato con assert che i risultati coincidono con quelli di os.path.

Leggere, scrivere, cercare

q = Path("n.txt")
q.write_text("è", encoding="utf-8")
q.read_text(encoding="utf-8")            # 'è'

list(Path(".").glob("*.txt"))            # solo la cartella
list(Path(".").rglob("*.txt"))           # anche le sottocartelle

Indica sempre encoding: senza, Python usa quello del sistema, che cambia da una macchina all'altra. Path.glob("*.txt") restituisce gli stessi file di glob.glob.

La trappola: / con un percorso assoluto

Path("/a") / "/etc" / "x"      # PosixPath('/etc/x')

Se un pezzo è assoluto, scarta tutto quello che veniva prima. Succede davvero quando il pezzo viene da input dell'utente (Path(base) / nome_file): un nome che inizia con / esce dalla cartella base. os.path.join si comporta allo stesso modo. Se il nome arriva dall'esterno, risolvi e controlla:

dest = (base / nome).resolve()
if not dest.is_relative_to(base.resolve()):   # Python 3.9+
    raise ValueError("percorso fuori dalla cartella")

Velocità

Misure (Python 3.12.15, macOS, migliore di 5 serie; cartella con 601 file, 301 .txt):

Operazione Tempo
os.path.join(...) ~1,4 µs
Path / "sub" / "a.txt" ~4,0 µs
glob.glob ~1,1 ms
Path.glob ~1,4 ms
os.listdir + splitext ~1,2 ms
os.scandir ~0,7 ms
iterdir() + .suffix ~1,9 ms

Path è circa 3 volte più lento a costruire percorsi e un po' più lento sulle liste. Sono microsecondi: per una manciata di file non cambia nulla. Se scorri centinaia di migliaia di file in un ciclo caldo, os.scandir è la scelta più veloce.

Quando usare cosa

  • Codice normale, script, configurazioni: pathlib. Meno import e meno join annidati.
  • Ciclo caldo su molti file: os.scandir.
  • Librerie che chiedono stringhe: la maggior parte accetta già Path; altrimenti str(p).

Lo script che ha prodotto le misure è verifica/pathlib_confronto.py nel sorgente del sito. I tempi dipendono dalla macchina e dal disco; non li ho provati su Windows.