مدراء السياق
Context Managers
مدراء السياق — Context Managers
سبق أن استخدمت with open("file.txt") as f: دون التفكير كثيراً في ما يجري خلف الكواليس. with ليست مجرد اختصار — إنها آلية تضمن تنفيذ كود التنظيف (إغلاق ملف، تحرير اتصال، إعادة قفل mutex) حتى إذا حدث استثناء في المنتصف. هذا هو مدير السياق.
المشكلة بدون with
with تجعل try/finally ضمنياً وتُخفي الكود المتكرر. لكن كيف تعمل؟
بروتوكول مدير السياق — Context Manager Protocol
أي كائن ينفّذ طريقتين يمكن استخدامه مع with:
__enter__(self)— تُنفَّذ عند دخول كتلةwith، تُرجع قيمة تُسنَد بـas__exit__(self, exc_type, exc_val, exc_tb)— تُنفَّذ عند الخروج من الكتلة، سواء بنجاح أو بخطأ
معاملات __exit__ تُخبرك عن الاستثناء إن وُجد:
- إذا لم يكن هناك استثناء: الثلاثة تكون
None - إذا أرجعت
True: الاستثناء يُلغى ولا يُنتشر - إذا أرجعت
Falseأو لم تُرجع: الاستثناء يستمر
contextlib.contextmanager — الطريقة الأسهل
بدلاً من كتابة class كاملة، يمكنك استخدام @contextmanager مع yield:
الجزء قبل yield يعادل __enter__، والجزء بعده (في finally) يعادل __exit__. استخدام try/finally مع yield يضمن تنفيذ كود التنظيف حتى عند الاستثناءات.
مثال عملي — قفل mutex مزيّف
تغيير وضع السياق — Changing Context State
مدراء السياق قادرون على تغيير حالة مؤقتة ثم إعادتها. مثال: تغيير الدقة العشرية مؤقتاً:
استخدام with مع كائنات متعددة
يمكن استخدام كائنات متعددة في with واحدة:
متى تكتب مدير سياق خاص بك؟
كلما وجدت نمطاً متكرراً مثل:
- افتح مورداً → استخدمه → أغلقه
- احفظ حالة → غيّرها → أعِدها
- ابدأ عملية → انهها (أو تراجع عن عواقبها)
هذا النمط يُرشّح لمدير سياق. الفائدة ليست فقط اختصار الكتابة، بل ضمان التنظيف حتى عند الأخطاء غير المتوقعة.