Skip to content

Latest commit

 

History

History
123 lines (75 loc) · 6.04 KB

File metadata and controls

123 lines (75 loc) · 6.04 KB

درس ششم: ماجرای event loop و چطور کار می‌کنه

تا اینجا یاد گرفتیم async و await چطور باعث می‌شن چند تا کار رو هم‌زمان انجام بدیم. ولی پشت صحنه چه کسی همهٔ این کارها رو مدیریت می‌کنه؟ پاسخ ساده‌اش اینه که یه چیزی به اسم event loop مسئول همه‌چیزه.


معنی event loop چیه؟

حلقهٔ رویداد یا همون event loop مثل یه مدیر پرجنب‌وجوشه که دائم بین کارها می‌چرخه و می‌گه:

«کدوم coroutine الان آماده‌ست اجرا بشه؟ کدوم باید منتظر بمونه؟»

در واقع event loop یه جور زمان‌بندی‌کننده‌ست. مطمئن می‌شه که هیچ کار بی‌دلیلی متوقف نشه و CPU هم همیشه مشغول باشه.


یه مثال واقعی

فرض کن توی خونه داری چای درست می‌کنی و سه تا کار داری:

  • جوشوندن آب
  • دم کردن چای
  • آوردن لیوان

تو یه نفر بیشتر نیستی، ولی می‌تونی بین این کارها جابه‌جا بشی. وقتی آب روی گازه و هنوز نجوشیده، لازم نیست بایستی و فقط نگاهش کنی. می‌ری لیوان‌ها رو آماده می‌کنی، بعد برمی‌گردی سراغ چای. این همون کاریه که event loop تو برنامه انجام می‌ده.


پشت صحنه چطور کار می‌کنه؟

‏event loop یه صف از coroutineها داره. هر بار یکی از اون‌ها اجرا می‌شه تا جایی که به یه نقطهٔ انتظار برسه (مثلاً وقتی از await استفاده می‌کنی). در اون لحظه، loop اونو کنار می‌ذاره و سراغ کار بعدی می‌ره. وقتی زمان اون coroutine رسید، دوباره برش می‌گردونه تو صف و ادامه می‌ده.

همین جابه‌جایی مداوم باعث می‌شه همهٔ کارها ظاهراً هم‌زمان پیش برن.

یه مثال ببین:

import asyncio

async def task(name, delay):
    print(f"{name} started")
    await asyncio.sleep(delay)
    print(f"{name} finished after {delay} seconds")

async def main():
    loop = asyncio.get_running_loop()
    print("Event loop started:", loop)

    await asyncio.gather(
        task("Task A", 2),
        task("Task B", 3),
        task("Task C", 1)
    )
    print("All tasks completed!")

asyncio.run(main())

در اینجا حلقهٔ رویداد همهٔ کارها رو با هم شروع می‌کنه. هرکدوم که به sleep می‌رسن، کنار گذاشته می‌شن تا زمانشون تموم بشه، و در این بین بقیه کارها اجرا می‌شن. در نهایت وقتی همه تموم شدن، پیام آخر چاپ می‌شه.


چرا این روش مفیده؟

فرض کن برنامه‌ای داری که باید چند تا کار زمان‌بر انجام بده، مثلاً:

  • دریافت داده از API
  • ذخیرهٔ اطلاعات توی پایگاه داده
  • ارسال ایمیل برای کاربر

اگه بخوای این کارها رو به شکل عادی و پشت سر هم انجام بدی، باید برای هر کدوم صبر کنی تا تموم شه و این باعث می‌شه زمان زیادی از دست بره. ولی با event loop، می‌تونی همهٔ این کارها رو هم‌زمان انجام بدی و از زمان انتظار یکی برای انجام دادن دیگری استفاده کنی.


نگاه عمیق‌تر به event loop

داخل حلقهٔ رویداد چند بخش مهم وجود داره:

  1. صف آماده‌ها (Ready Queue): coroutineهایی که الان می‌تونن اجرا بشن.
  2. صف منتظرها (Waiting Queue): coroutineهایی که منتظر یه رویدادن (مثلاً پاسخ سرور یا گذشت زمان).
  3. بخش بیدارباش (Wakeup): وقتی یکی از coroutineها آماده می‌شه، از صف انتظار خارج می‌شه و برمی‌گرده به صف آماده‌ها.

این چرخه تا وقتی کارها تموم نشن ادامه داره. به همین دلیل بهش می‌گن حلقه.


مشاهدهٔ event loop در عمل

پایتون اجازه می‌ده خودت event loop فعلی رو ببینی:

import asyncio

async def show_loop():
    loop = asyncio.get_running_loop()
    print("Current loop:", loop)

asyncio.run(show_loop())

این کد یه نمونه از event loop فعلی رو برمی‌گردونه که وظیفه داره coroutineها رو مدیریت کنه. معمولاً نیازی نیست خودت باهاش مستقیم کار کنی، چون asyncio همه‌چیز رو خودکار کنترل می‌کنه.


نقش تابع asyncio.run

تابع asyncio.run در واقع خودش یه event loop موقتی می‌سازه، coroutine اصلی رو داخلش اجرا می‌کنه، و بعد از پایان، اون حلقه رو می‌بنده. این یعنی در هر لحظه فقط یه loop فعاله. اگه خودت یه loop جداگانه بسازی، باید مطمئن باشی داری کنترل کاملش رو در دست می‌گیری.


جمع‌بندی

  • حلقهٔ رویداد مغز پشت سیستم غیرهم‌زمان پایتونه.
  • وظیفهٔ اون زمان‌بندی coroutineها و جابه‌جایی بینشونه.
  • با event loop می‌شه چند کار رو هم‌زمان انجام داد بدون اینکه برنامه قفل کنه.
  • تابع asyncio.run خودش یه event loop می‌سازه و بعد از پایان کار اونو می‌بنده.

درس قبلی   |   درس بعدی