2.24. Upravitelji konteksta¶
Naredba with pokreće kod za postavljanje, zatim tijelo, pa kod za pospremanje – uz jamstvo da se pospremanje izvrši čak i kad tijelo otkaže usred izvođenja. Par metoda koji pruža postavljanje i pospremanje naziva se upravitelj konteksta.
Oblik je:
with <expression> as <name>:
<body>
Izraz vraća upravitelja konteksta. Python poziva njegovu metodu __enter__, po izboru veže rezultat na <name>, izvršava tijelo i zatim poziva __exit__ – bilo da je tijelo završilo normalno ili izazvalo iznimku.
__exit__ se izvršava na kraju bloka što god se unutar njega dogodilo.¶
2.24.1. Korištenje upravitelja konteksta¶
Kanonski primjer je otvaranje datoteke:
with open("data.txt") as f:
text = f.read()
# f is now closed, even if read() failed
open() vraća objekt datoteke koji je i sam upravitelj konteksta; __enter__ vraća datoteku, a __exit__ je zatvara. Blok with čini „uvijek zatvori datoteku kad završiš” zadanim ponašanjem umjesto nečega čega se pozivatelj mora sjetiti.
2.24.1.1. Više upravitelja konteksta¶
Jedna naredba with može odjednom ući u nekoliko upravitelja konteksta, odvojenih zarezima:
with open("input.txt") as src, open("output.txt", "w") as dst:
dst.write(src.read())
Ekvivalentno dvama ugniježđenim blokovima with, ali pljosnatije. U upravitelje se ulazi slijeva nadesno, a izlazi obrnutim redoslijedom; ako __enter__ na desnom upravitelju izazove iznimku, __exit__ lijevog upravitelja se ipak izvrši.
2.24.2. Pisanje upravitelja konteksta¶
Bilo koja klasa s metodama __enter__ i __exit__ radi kao upravitelj konteksta:
class Section:
def __init__(self, label):
self.label = label
def __enter__(self):
print("---", self.label, "---")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("--- end", self.label, "---")
return False
with Section("setup"):
print("doing the work")
Izlaz:
--- setup ---
doing the work
--- end setup ---
__exit__ prima tri argumenta koji opisuju iznimku koja je okončala blok, ili tri None vrijednosti ako je blok završio normalno. Vraćanje False (ili None) dopušta da se svaka iznimka propagira nakon pospremanja; vraćanje True bi je progutalo.
Koristi upravitelje konteksta za svaki resurs koji ima životni ciklus „otvori / zatvori” ili „zauzmi / oslobodi” – ne samo za datoteke. Obrazac drži čišćenje uparenim s postavljanjem na mjestu gdje su oba uvedena, pa zaboravljeno zatvaranje usred dugačke funkcije ne može procuriti resurs.