خانه / آموزش‌ها / آموزش Asyncio و برنامه‌نویسی ناهمگام در پایتون

آموزش Asyncio و برنامه‌نویسی ناهمگام در پایتون

🐍 HomeOfPython
|
📅 1404/10/18

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

برنامه‌نویسی ناهمگام (Asynchronous) یکی از مفاهیم قدرتمند در پایتون مدرن است که به شما اجازه می‌دهد کارهایی که زمان‌بر هستند (مثل درخواست‌های شبکه یا خواندن فایل) را بدون متوقف کردن کل برنامه انجام دهید.

مفهوم همگام (Sync) در برابر ناهمگام (Async)

در برنامه‌نویسی معمولی (Synchronous)، کدها خط به خط اجرا می‌شوند. اگر یک خط ۱۰ ثانیه طول بکشد، کل برنامه ۱۰ ثانیه متوقف می‌شود. اما در Asynchronous، برنامه می‌تواند در حین انتظار برای آن ۱۰ ثانیه، کارهای دیگری انجام دهد.

تصور کنید در یک کافی‌شاپ هستید:

  1. روش همگام (Sync): صندوق‌دار سفارش شما را می‌گیرد، صبر می‌کند تا قهوه آماده شود، آن را به شما می‌دهد و سپس سراغ مشتری بعدی می‌رود.
  2. روش ناهمگام (Async): صندوق‌دار سفارش شما را می‌گیرد، آن را به آشپزخانه می‌دهد و بلافاصله سفارش نفر بعدی را می‌گیرد. وقتی قهوه آماده شد، به شما تحویل داده می‌شود.

تعریف Coroutine با async و await

برای ساخت یک تابع ناهمگام، از کلمه کلیدی async def استفاده می‌کنیم. برای اجرا کردن و منتظر ماندن نتیجه آن، از await استفاده می‌کنیم.

نکته مهم: توابع async را نمی‌توان مثل توابع معمولی صدا زد؛ آن‌ها باید توسط یک "اجراکننده" مثل asyncio.run() مدیریت شوند.

Python
python
# مثال ۲: ساختار کلی (Static Snippet)
async def fetch_data():
    data = await download_from_server() # صبر می‌کند اما برنامه قفل نمی‌شود
    return data

اجرای پشت سر هم (Sequential) در Async

حتی در حالت Async، اگر از await پشت سر هم استفاده کنید، کدها نوبت به نوبت اجرا می‌شوند. قدرت واقعی زمانی است که کارها را همزمان کنیم (که در بخش پیشرفته می‌بینیم).

Python

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

در این سطح به مدیریت همزمانی واقعی (Concurrency)، کار با Gather، مدیریت خطاها و نکات پرفرمنس در Asyncio می‌پردازیم.

اجرای همزمان با asyncio.gather

برای اینکه چندین کار واقعاً به صورت همزمان (Concurrent) جلو بروند، باید آن‌ها را با هم زمان‌بندی کنیم. تابع asyncio.gather به ما اجازه می‌دهد چندین Coroutine را همزمان استارت بزنیم.

Python

مدیریت Timeout (محدودیت زمانی)

گاهی اوقات یک عملیات شبکه ممکن است خیلی طول بکشد. در برنامه‌های حرفه‌ای، حتماً باید از asyncio.wait_for برای جلوگیری از فریز شدن روی یک تسک استفاده کنید.

Python

اشتباه رایج: Blocking Code

یکی از بزرگترین اشتباهات در برنامه‌نویسی Async، استفاده از توابع مسدودکننده (Blocking) مثل time.sleep() یا درخواست‌های سنگین CPU داخل یک تابع async است. این کار کل Event Loop را متوقف می‌کند.

python
# مثال اشتباه (Static - Do Not Run in Prod)
import time

async def bad_coroutine():
    # این خط غلط است! کل برنامه را فریز می‌کند
    time.sleep(5) 
    print("این کار غلط بود")

# راه حل درست:
# استفاده از await asyncio.sleep(5)
# یا اجرای کارهای سنگین CPU در یک Thread جداگانه با run_in_executor

اجرای Task در پس‌زمینه (Fire and Forget)

گاهی می‌خواهیم یک تسک شروع شود اما منتظر نتیجه آن نمانیم (مثلاً ارسال لاگ یا ایمیل). برای این کار از asyncio.create_task استفاده می‌کنیم.

Python