Context Managers & with
Context manager adalah objek yang menjamin setup dan cleanup berjalan dengan benar — bahkan saat terjadi error. Kamu pasti sudah pernah pakai saat membuka file:
with open("data.txt", "r") as f:
isi = f.read()
# File otomatis ditutup di sini — bahkan jika terjadi error di dalam blok
Kenapa with Dibutuhkan?
Tanpa with, kita harus manual pakai try/finally:
f = open("data.txt", "r")
try:
isi = f.read()
# kalau error di sini, f.close() di bawah TETAP dipanggil
finally:
f.close()
with mengotomatisasi pola ini. File (atau resource apa pun) dijamin ditutup, sekalipun blok melempar exception.
Protokol __enter__ dan __exit__
Class apa pun bisa jadi context manager dengan mengimplementasikan dua dunder method ini:
class Timer:
def __enter__(self):
import time
self.start = time.time()
return self # nilai ini di-assign ke variabel setelah "as"
def __exit__(self, exc_type, exc_val, exc_tb):
import time
elapsed = time.time() - self.start
print(f"Selesai dalam {elapsed:.3f} detik")
# return False (default) = jangan swallow exception
with Timer() as t:
# kerjakan sesuatu
total = sum(range(1_000_000))
# Output: Selesai dalam 0.012 detik
__enter__dipanggil saat masuk blokwith. Return-nya di-bind ke variabel setelahas.__exit__dipanggil saat keluar blok — baik normal maupun karena exception. Tiga parameternya berisi info exception (atauNonejika tidak ada).
Cara Lebih Mudah: @contextmanager
Kalau enggan membuat class, pakai decorator @contextmanager dari contextlib + generator:
from contextlib import contextmanager
@contextmanager
def buka_koneksi(nama):
print(f"Buka koneksi ke {nama}")
try:
yield nama # "setup selesai, berikan resource ke blok with"
finally:
print(f"Tutup koneksi ke {nama}") # cleanup, selalu jalan
with buka_koneksi("database") as conn:
print(f"Query {conn}...")
# Buka koneksi ke database
# Query database...
# Tutup koneksi ke database
Nested with
Boleh gabung beberapa context manager dalam satu baris:
with open("input.txt") as src, open("output.txt", "w") as dst:
dst.write(src.read())
# Kedua file dijamin ditutup
Use Case Umum
- File — tutup otomatis
- Lock / semaphore —
with lock: ...jamin lock dilepas - Database transaction — commit saat sukses, rollback saat error
- Patching sementara — ubah env variable, lalu kembalikan
- Timer / profiling — catat waktu eksekusi blok kode