خانه / آموزش‌ها / مدیریت کانتکست (Context Managers) در پایتون

مدیریت کانتکست (Context Managers) در پایتون

🐍 HomeOfPython
|
📅 1404/10/18

سطح مقدماتی (Beginner Level)

مدیریت منابع (Resource Management) یکی از مهم‌ترین بخش‌های برنامه‌نویسی است. وقتی با فایل‌ها، دیتابیس‌ها یا شبکه کار می‌کنیم، باید مطمئن شویم که منابع پس از استفاده آزاد می‌شوند. در پایتون، دستور with و مفهوم Context Manager این کار را به صورت خودکار و ایمن انجام می‌دهند.

۱. دستور with و چرایی استفاده از آن

در حالت عادی، اگر فایلی را باز کنید و فراموش کنید آن را ببندید (یا اروری رخ دهد که مانع بستن شود)، حافظه اشغال می‌ماند. دستور with تضمین می‌کند که حتی در صورت بروز خطا، عملیات "پاک‌سازی" (مثل بستن فایل) انجام شود.

مثال اول: مقایسه روش سنتی و روش with

در این مثال می‌بینیم که روش قدیمی چقدر طولانی و مستعد خطاست.

python
# Static: Traditional way (Not recommended)
# We have to manually close the file, even if an error occurs.
file = open("example.txt", "w")
try:
    file.write("Hello World")
finally:
    file.close()  # Must manually close

مثال دوم: استفاده از with (روش استاندارد)

این کد همان کار بالا را انجام می‌دهد اما بسیار تمیزتر است. پایتون به صورت خودکار فایل را می‌بندد.

Python

مثال سوم: مدیریت چندین منبع همزمان

شما می‌توانید چندین کانتکست را در یک دستور with مدیریت کنید (از پایتون ۳.۱۰ به بعد می‌توان از پرانتز استفاده کرد).

Python

۲. کاربرد with در قفل‌ها (Locks)

علاوه بر فایل‌ها، with در برنامه‌نویسی چندنخی (Threading) برای مدیریت قفل‌ها بسیار کاربرد دارد تا از deadlock جلوگیری شود.

مثال اول: استفاده از Lock

Python

سطح پیشرفته (Professional Level)

در این سطح یاد می‌گیریم که with واقعاً چطور کار می‌کند (پروتکل Context Manager) و چگونه کلاس‌ها و توابع خودمان را با قابلیت استفاده در with بسازیم.

۱. پروتکل Context Management (__enter__ و __exit__)

هر کلاسی که دارای دو متد جادویی __enter__ و __exit__ باشد، یک Context Manager است.

  • __enter__: وقتی وارد بلوک with می‌شویم اجرا می‌شود. خروجی آن در متغیر جلوی as قرار می‌گیرد.
  • __exit__: وقتی بلوک تمام شود (یا ارور رخ دهد) اجرا می‌شود.

مثال اول: ساخت یک Context Manager ساده

یک کلاس می‌سازیم که ورود و خروج به بلوک را لاگ می‌کند.

Python

مثال دوم: مدیریت خطا در __exit__

اگر در بلوک with خطایی رخ دهد، اطلاعات آن به __exit__ پاس داده می‌شود. اگر __exit__ مقدار True برگرداند، خطا سرکوب (Suppress) می‌شود؛ در غیر این صورت برنامه کرش می‌کند.

Python

۲. ماژول contextlib و دکوراتور @contextmanager

نوشتن کلاس کامل برای کارهای ساده ممکن است سربار داشته باشد. ماژول contextlib اجازه می‌دهد با استفاده از Generator ها، Context Manager بسازیم.

مثال اول: تبدیل تابع به Context Manager

از yield برای جدا کردن کدهای قبل از ورود (__enter__) و بعد از خروج (__exit__) استفاده می‌شود.

Python

مثال دوم: contextlib.suppress

یک ابزار آماده برای نادیده گرفتن خطاهای خاص بدون نیاز به بلوک try-except طولانی.

Python

مثال سوم: contextlib.closing

برای اشیایی که متد close() دارند اما پروتکل Context Manager را پیاده‌سازی نکرده‌اند (مثل برخی کانکشن‌های قدیمی یا urllib) استفاده می‌شود.

python
# Static: Using closing for objects lacking context support
from contextlib import closing
from urllib.request import urlopen

# urlopen in older python versions might not support 'with' directly
# closing() calls .close() automatically upon exit
with closing(urlopen("https://www.homeofpython.com")) as page:
    content = page.read()