نوشتن context manager با یک تابع جنراتور
ماژول contextlib دکوراتوری به نام @contextmanager ارائه میدهد که با استفاده از yield میتوان یک context manager کامل را تنها با یک تابع نوشت، بدون نیاز به کلاس و دو متد جداگانه.
from contextlib import contextmanager
import time
@contextmanager
def timer():
start = time.time()
try:
yield
finally:
print(f"زمان سپریشده: {time.time() - start:.4f} ثانیه")
with timer():
total = sum(range(1_000_000))هر کدی که پیش از yield نوشته شود معادل __enter__ است و هر کدی که بعد از آن (در بلوک finally) بیاید معادل __exit__. اگر داخل بلوک with خطایی رخ دهد، همان خطا در نقطهی yield بازپخش میشود، بنابراین استفاده از try/finally برای تضمین اجرای کد پاکسازی ضروری است.
ماژول contextlib ابزارهای مفید دیگری نیز دارد، از جمله suppress برای نادیده گرفتن خطاهای خاص و ExitStack برای مدیریت چند context manager بهصورت پویا. این ابزارها بهویژه در کد کتابخانهای و ابزارهای خط فرمان حرفهای بسیار پرکاربرد هستند.