Bağlam yöneticisi — with bloğuna giriş ve çıkış davranışını tanımlayan bir nesnedir, kaynakların (dosyalar, bağlantılar vb.) otomatik yönetimini sağlar. Sınıfta __enter__ ve __exit__ metodlarıyla veya contextlib modülünden @contextmanager dekoratörü ile uygulanır.
class FileManager: def __init__(self, filename, mode): self.filename = filename self.mode = mode self.file = None def __enter__(self): self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close() with FileManager('test.txt', 'w') as f: f.write('Hello')
Önemli noktalar: __exit__ içinde hataları doğru bir şekilde işlemek önemlidir; hataları bastırmak için True döndürmek ve hatalardan kaynaklanan açık kaynaklarla ilgili dikkatli olmak gerekir.
Soru: with bloğunda bir istisna oluşursa, Python __exit__ metodunu çağırır mı? Hata parametreleri nasıl iletilir?
Cevap: Evet, __exit__ metodu her zaman çağrılır, hatta bir istisna oluşsa bile. Bu metotta istisna türü, değeri ve traceback iletilir. Eğer __exit__ True döndürürse, istisna bastırılır.
class Simple: def __enter__(self): print('Giriş') def __exit__(self, exc_type, exc_val, exc_tb): print('Çıkış') print(exc_type, exc_val) return True # hata "dışarıya" çıkmaz with Simple(): raise ValueError('boom!')
Hikaye
__exit__'i uygulamayı unuttular - bir hata durumunda dosya kapatılmadı, bu da dosya tanıtıcılarının sızmasına ve çok sayıda dosya ile çalışırken hatalara yol açtı.Hikaye
__exit__ metodunda tüm istisnalar için True döndürdüğünü gördüler. Bu, hataları "bastırdı" ve dikkatsiz hatalara ve veri bütünlüğünün bozulmasına yol açtı, çünkü mantık işlemin başarılı olduğunu düşündü.Hikaye
contextlib modülünden @contextmanager dekoratörünü kullandılar, ancak hataları yield içinde işlemekten unuttular; bu yüzden bağlantı kapanmadı, kod çöktüğünde sunucu açık bağlantılarla "kilitlendi".