CodeGym /Corso Java /Python SELF IT /Operatore with

Operatore with

Python SELF IT
Livello 21 , Lezione 3
Disponibile

4.1 Chiusura del file e gestione degli errori

A volte, quando si legge un file, si verificano errori o eccezioni e il file rimane non chiuso. Questo può potenzialmente portare a una perdita di memoria o perdita di file handler. Pertanto, il lavoro con il file deve essere racchiuso in un blocco try-except.

Supponiamo che tu abbia il codice:


file = open('example.txt', 'a') # Apriamo il file
file.write("This is a new line added to the file.")
file.close()  # Chiudiamo il file

Deve essere incapsulato in un blocco try-except:


try:
    file = open('example.txt', 'a')  # Apriamo il file
    file.write("This is a new line added to the file.")
    file.close()  # Chiudiamo il file
except FileNotFoundError:
    print("File not found")
    file.close()  # Chiudiamo il file

Per evitare di scrivere due volte il metodo close(), puoi metterlo in un blocco finally:


try:
    file = open('example.txt', 'a')  # Apriamo il file
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    file.close()  # Chiudiamo il file

Questo codice sembra bello, ma... non funziona, perché la variabile file è definita solo nel blocco try e non è accessibile dai blocchi except e finally.

Quindi dobbiamo definire la variabile a un livello superiore:


file = None
try:
    file = open('example.txt', 'a')  # Apriamo il file
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    file.close()  # Chiudiamo il file

Questa soluzione è migliore, ma ha anche dei difetti. Ad esempio, se il file non viene mai aperto, la variabile file rimarrà None. E allora tentare di chiudere il file genererà un errore — ci sarà un tentativo di chiamare il metodo close() su un oggetto inesistente.

Quindi dobbiamo aggiungere un controllo prima di chiamare il metodo close():


file = None
try:
    file = open('example.txt', 'a')  # Apriamo il file
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    if file:
        file.close()  # Chiudiamo il file

Se sei sorpreso che 3 righe di codice si siano trasformate in 9, non sei solo. Fortunatamente, c'è già una soluzione pronta a questo problema, di cui parleremo di seguito.

4.2 Operatore with

L'operatore with in Python fornisce un modo conveniente di gestire le risorse, come i file, assicurando che vengano chiuse automaticamente dopo il completamento del blocco with. Questo semplifica il codice e previene le perdite di risorse, come i file non chiusi.

Sintassi generale dell'operatore with:


with espressione as variabile:
    lavoro con la variabile

L'operatore with viene utilizzato per incapsulare l'esecuzione di un blocco di codice con un gestore di contesto. Alla utilizzo dell'operatore with, Python chiama automaticamente i metodi __enter__() e __exit__() dell'oggetto gestore di contesto, il che semplifica la gestione delle risorse.

Esempio di utilizzo di with per lavorare con i file:


with open('example.txt', 'w') as file:
    file.write("Hello, World!\n")
    file.write("This is a test file.\n")

In questo esempio, il file example.txt viene aperto in modalità scrittura, e il nome del file viene associato alla variabile file. Il blocco di codice all'interno del with chiude automaticamente il file dopo aver completato tutte le operazioni di scrittura.

4.3 Chiusura automatica del file

Uno dei principali vantaggi dell'utilizzo dell'operatore with è la chiusura automatica del file dopo il completamento del blocco di codice. Ciò avviene anche in caso di eccezione, rendendo il codice più sicuro e affidabile.

Esempio di chiusura automatica del file:


try:
    with open('example.txt', 'w') as file:
        file.write("Hello, World!\n")
        file.write("This is a test file.\n")
        # Eccezione per verificare che il file si chiuda comunque
        raise Exception("Something went wrong")
except Exception as e:
    print(f"Caught an exception: {e}")
# Qui il file è già chiuso

Usa sempre l'operatore with quando lavori con i file. È semplice e ti aiuta a evitare una miriade di errori.

4.4 Come funziona l'operatore with

Alla base del funzionamento dell'operatore with vi sono i metodi __enter__() e __exit__(), che devono essere implementati nella classe utilizzata come gestore di contesto.

Affinché un oggetto possa essere utilizzato con l'operatore with, deve implementare i metodi __enter__() e __exit__(). Questi metodi definiscono il comportamento all'ingresso e all'uscita del contesto.

Metodo __enter__()

Il metodo __enter__() è chiamato all'entrata nel blocco with. Esegue l'inizializzazione della risorsa e restituisce un oggetto che sarà assegnato alla variabile specificata dopo as.

Metodo __exit__()

Il metodo __exit__() è chiamato alla fine del blocco with. Esegue operazioni di pulizia come il rilascio delle risorse o la chiusura dei file. Il metodo accetta tre argomenti: exc_type, exc_val e exc_tb, che contengono informazioni sull'eccezione, se si verifica.

  • exc_type: il tipo di eccezione (ad esempio, ZeroDivisionError).
  • exc_val: il valore dell'eccezione (ad esempio, il messaggio di errore).
  • exc_tb: la traccia dello stack dell'eccezione.

Se il metodo __exit__() restituisce True, l'eccezione sarà soppressa. Se restituisce False, l'eccezione sarà nuovamente sollevata.

Esempio:


class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            print(f"An exception occurred: {exc_type}, {exc_val}")
        return False  # L'eccezione non viene soppressa
        
with MyContextManager() as manager:
    print("Inside the with block")
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION