Crearea Managerilor de Context cu contextlib (@contextmanager) în Python

Funcții Toate versiunile Python 3 Q&A / Distribuie cod

Ghid complet pentru crearea managerilor de context prin generatoare cu decoratorul @contextmanager: eliberarea automată a resurselor, gestionarea tranzacțiilor și contextlib.suppress.

Sintaxă
from contextlib import contextmanager
@contextmanager
def cronometru():
    start = time.perf_counter()
    yield
    print(time.perf_counter() - start)

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.

Crearea unui cronometru de performanță cu @contextmanager
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:

Gestionarea unei tranzacții de baze de date cu rollback automat
@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 de try ... 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ă verificare if ctx is not None.
Comunitate & Schimb de cunoștințe

Întrebări & Exemple de Cod: Crearea Managerilor de Context cu contextlib (@contextmanager)

Ai o nelămurire despre utilizarea comenzii Crearea Managerilor de Context cu contextlib (@contextmanager) sau ai descoperit un truc / fragment de cod util? Distribuie-l cu ceilalți programatori!

💬

Fii primul care pune o întrebare sau distribuie un fragment de cod / prompt!

Nu au fost adăugate încă întrebări sau exemple de cod pentru această pagină. Dacă ai întâlnit o problemă sau ai un snippet util, adaugă-l mai jos pentru a-i ajuta pe ceilalți.

Comunitate Adaugă o întrebare sau distribuie un cod

Moderare & Siguranță:

Pentru a menține calitatea și securitatea informațiilor, fiecare întrebare sau fragment de cod/prompt este analizat (manual sau prin moderare asistată de AI) înainte de publicare.