L'Istruzione with

In questa lezione parleremo dell'istruzione with: si tratta di una delle tante migliorie apportate al linguaggio nel corso degli anni, proposta e spiegata nel dettaglio nella PEP 343 sul sito della Python Foundation.

In questo tutorial vedremo perché è utile e come usarla. Come abbiamo già detto in precedenza, quando lavoriamo con dei file, è sempre molto importante ricordarsi di chiuderli una volta usati, questo per evitare problemi sul file stesso e per sprechi di risorse preziose, come la memoria RAM.

Supponiamo di avere un file testuale chiamato zazà.txt e di volerne leggere il contenuto:

zenigata = open("zazà.txt","r")
for riga in zenigata:
    print(riga)
zenigata.close()

# output
"Lupen
Was
Here!
:-D"

Abbiamo aperto il file utilizzando la funzione open(). Verifichiamo se il file sia stato effettivamente chiuso in questo modo:

print(zenigata.closed)

# output
True

Con l'istruzione with possiamo risparmiare una riga di codice ogni volta che apriamo un file, nello specifico la riga con l'istruzione close(), perché essa fa in modo che il file venga chiuso automaticamente quando si esce dal blocco del with. La usiamo in questo modo:

with open("zazà.txt","r") as zenigata:
    for riga in zenigata:
        print(riga)

print(zenigata.closed)

"Lupen
Was
Here!
:-D"

# output
True

Ed ecco che otteniamo lo stesso risultato, ma in maniera più pulita e decisamente più sicura: usare i file può comportare la comparsa di bug, e with ci permette di mitigare questa possibilità. Consideriamo il caso in cui stiamo lavorando con un file testuale contenente svariati numeri e vogliamo aggiungerli ad una lista dopo averli convertiti in float:

numeri = []
dati = open("dati_importanti.txt", "r")

for num in dati:
    numeri.append(float(num))
dati.close()

Per essere sicuri di poter chiudere il file qualunque cosa succeda, anche in caso di potenziali errori, dobbiamo utilizzare try, except e finally in questa maniera:

numeri = []
dati = open("dati_importanti.txt","r")

try:
    for num in dati:
        numeri.append(float(num))
except ValueError:
    print("Errore!!!")
finally:
    dati.close()

print(dati.closed)

# output
Errore!!!

True

È proprio per casi come questo che with è stato implementato come miglioria. Verifichiamo che il file venga chiuso automaticamente quando si esce dal blocco del with usando comunque try ed except, ma senza il blocco finally in cui andiamo a chiudere il file:

numeri = []
with open("dati_importanti.txt","r") as dati:
    try:
        for num in dati:
            numeri.append(float(num))
    except ValueError:
        pass

print(dati.closed)

# output
True