Protocolul de gestionare a contextului (instrucțiunea with) este mecanismul consacrat prin care Python garantează că resursele alocate (fișiere, conexiuni la baze de date, lock-uri de thread-uri) sunt eliberate deterministic. Scrierea unei clase complete cu metodele dunder __enter__ și __exit__ poate fi însă redundantă. Decoratorul @contextmanager din modulul contextlib permite transformarea oricărei funcții generatoare simple într-un manager de context complet și robust.
import time
from contextlib import contextmanager
@contextmanager
def cronometreaza(nume_sarcina: str):
start = time.perf_counter()
print(f"[{nume_sarcina}] Start execuție...")
try:
# Punctul 'yield' transmite controlul blocului de cod din interiorul 'with':
yield
finally:
# Codul de după yield se execută GARANTAT la ieșirea din bloc,
# chiar dacă în interior a apărut o excepție!
durata = time.perf_counter() - start
print(f"[{nume_sarcina}] Finalizat în {durata:.4f} secunde.")
# Utilizare practică:
with cronometreaza("Calcul matricial"):
suma = sum(i ** 2 for i in range(1_000_000))
Returnarea unei Resurse din clauza yield
Dacă doriți ca managerul de context să furnizeze o resursă în variabila definită prin clauza as (cum face open() as fisier), transmiteți valoarea ca argument al instrucțiunii yield valoare:
@contextmanager
def tranzactie_sigura(conexiune):
cursor = conexiune.cursor()
cursor.execute("START TRANSACTION;")
try:
yield cursor
conexiune.commit()
print("Tranzacție salvată cu succes (COMMIT).")
except Exception as eroare:
conexiune.rollback()
print(f"Tranzacție anulată (ROLLBACK) din cauza: {eroare}")
raise # Repropagăm eroarea după rollback!
finally:
cursor.close()
# Utilizare:
# with tranzactie_sigura(db) as c:
# c.execute("UPDATE solduri SET total = total - 100 WHERE id = 1;")
Utilitare Rapide din Modulul contextlib
contextlib.suppress(*exceptions): Ignoră silențios excepțiile specificate, eliminând blocurile verbos detry ... except: pass:from contextlib import suppress # Șterge fișierul dacă există, dar nu aruncă eroare dacă lipsește: with suppress(FileNotFoundError): os.remove("fisier_temporar.txt")contextlib.nullcontext(val): Un manager de context de tip no-op (nu face nimic), util când doriți ca un parametru opțional de context manager să poată fi pasat fără verificareif ctx is not None.