Asyncio
Asyncio یک کتابخانه مهم در پایتون برای برنامهنویسی غیرهمزمان (asynchronous) است که امکان اجرای همزمان چندین کار بدون استفاده از thread یا process سنتی را فراهم میکند. این کتابخانه برای عملیات I/O-محور مانند درخواستهای شبکه، خواندن و نوشتن فایل، و دسترسی به دیتابیس اهمیت ویژهای دارد، زیرا از زمانهای انتظار بلاکشونده جلوگیری میکند و کارایی برنامه را افزایش میدهد.
در توسعه نرمافزار و معماری سیستم، Asyncio بهویژه برای سرویسهای بکاند، میکروسرویسها، پردازش دادههای بلادرنگ و سیستمهای ارتباطی real-time مناسب است. مفاهیم کلیدی شامل coroutines با استفاده از async/await، مدیریت تسکها با asyncio.gather یا asyncio.wait، مدیریت منابع به صورت غیرهمزمان و طراحی الگوریتمها و ساختارهای داده غیرمسدودکننده است. ترکیب اصول OOP با Asyncio امکان ایجاد سیستمهای ماژولار، قابل نگهداری و قابل تست را فراهم میکند.
پس از مطالعه این آموزش، خواننده قادر خواهد بود برنامههای غیرهمزمان کارآمد و مقیاسپذیر توسعه دهد، مفاهیم اصلی Asyncio را درک کند و از اشتباهات رایج مانند memory leaks و خطاهای مدیریت استثنا جلوگیری کند. مثالهای عملی مهارتهای حل مسئله و تفکر الگوریتمی را تقویت میکنند و امکان پیادهسازی فوری این تکنیکها در پروژههای حرفهای را فراهم میسازند.
مثال پایه
pythonimport asyncio
async def greet(name):
await asyncio.sleep(1)
print(f"سلام، {name}!")
async def main():
tasks = \[greet("Alice"), greet("Bob"), greet("Charlie")]
await asyncio.gather(*tasks)
if name == "main":
asyncio.run(main())
این کد اصول اصلی Asyncio را نشان میدهد: coroutines، event loop و زمانبندی تسکها. تابع greet یک coroutine است که با async تعریف شده و با await asyncio.sleep(1) یک عملیات غیرهمزمان شبیهسازی میکند. در این مدت، event loop میتواند سایر تسکها را اجرا کند و اجرای همزمان را ممکن سازد.
در main، یک لیست از تسکها ایجاد میشود و با asyncio.gather اجرا میشوند. gather تضمین میکند که تمام تسکها بهطور همزمان و بدون مسدود کردن یکدیگر اجرا شوند. asyncio.run loop رو ایجاد میکند، coroutine اصلی را اجرا میکند و پس از اتمام، loop را بهدرستی میبندد تا از memory leak جلوگیری شود.
این الگو میتواند مستقیماً برای ارسال اعلانها، اجرای همزمان چندین API call یا پردازش موازی I/O استفاده شود. یکی از سوالات رایج مبتدیان این است که چرا await نمیتواند خارج از coroutine استفاده شود؛ زیرا این کار باعث بروز SyntaxError میشود. gather نسبت به حلقههای متوالی، concurrency واقعی را فراهم میکند و زمان کل اجرا را کاهش میدهد.
مثال کاربردی
pythonimport asyncio
import aiohttp
class APIClient:
def init(self, urls):
self.urls = urls
async def fetch(self, session, url):
try:
async with session.get(url) as response:
data = await response.text()
print(f"{url} دریافت شد: {len(data)} کاراکتر")
except Exception as e:
print(f"خطا هنگام دریافت {url}: {e}")
async def run(self):
async with aiohttp.ClientSession() as session:
tasks = [self.fetch(session, url) for url in self.urls]
await asyncio.gather(*tasks)
if name == "main":
urls = \["[https://example.com](https://example.com)", "[https://httpbin.org/get](https://httpbin.org/get)", "[https://jsonplaceholder.typicode.com/posts](https://jsonplaceholder.typicode.com/posts)"]
client = APIClient(urls)
asyncio.run(client.run())
این مثال کاربرد Asyncio در درخواستهای شبکه را نشان میدهد. کلاس APIClient منطق fetch را در خود encapsulate کرده و اصول OOP را رعایت میکند. متد fetch با async with session را مدیریت میکند تا از memory leak جلوگیری شود و await session.get(url) اجازه میدهد که event loop سایر تسکها را در طول انتظار اجرا کند، که concurrency را افزایش میدهد.
متد run تمام تسکها را با asyncio.gather اجرا میکند و try/except اطمینان میدهد که خطاهای شبکه برنامه را متوقف نمیکنند. این الگو برای web scraping، batch API calls و پردازش موازی I/O مناسب است و ترکیب OOP و asynchronous programming کد تمیز، قابل نگهداری و قابل تست ارائه میدهد.
بهترین شیوهها و مشکلات رایج Asyncio:
بهترین شیوهها: تعریف coroutines شفاف، اجرای تسکها با gather یا wait، مدیریت منابع با async with، و handling exceptions برای اطمینان از پایداری. استفاده از asyncio.run برای شروع loop توصیه میشود.
مشکلات رایج: استفاده از await خارج از coroutine، نادیده گرفتن exceptions، استفاده از حلقههای متوالی برای I/O، منابع آزاد نشده که باعث memory leak میشوند. Debugging: فعال کردن debug mode، پیگیری تسکهای pending، و استفاده از logging برای وضعیت تسکها. بهینهسازی عملکرد: جلوگیری از await غیرضروری، دستهبندی تسکها، جلوگیری از عملیات blocking. امنیت: validate کردن ورودیها و handling درست exceptions برای جلوگیری از crash.
📊 جدول مرجع
Element/Concept | Description | Usage Example |
---|---|---|
Coroutine | تابعی که میتواند pause و resume شود | async def fetch_data(): await asyncio.sleep(1) |
async/await | کلمات کلیدی برای تعریف و اجرای coroutines | async def process(): await fetch_data() |
Event Loop | هستهای که coroutines و tasks را مدیریت میکند | loop = asyncio.get_event_loop() |
asyncio.gather | اجرای همزمان چندین task | await asyncio.gather(task1, task2) |
async with | مدیریت امن منابع غیرهمزمان | async with aiohttp.ClientSession() as session |
خلاصه و گامهای بعدی:
Asyncio ابزار قدرتمندی برای توسعه سیستمهای backend مقیاسپذیر و کارآمد است. یادگیری coroutines، task scheduling، مدیریت event loop و resource handling به توسعهدهندگان اجازه میدهد تا latency را کاهش دهند و کد غیرهمزمان قابل نگهداری بنویسند.
پس از Asyncio، توسعهدهندگان میتوانند کتابخانههای پیشرفتهتر مانند aiohttp، aiomysql و asyncpg را برای مدیریت HTTP requests و دسترسی به دیتابیس بررسی کنند. شروع با tasks کوچک و گسترش به microservices، پردازش real-time و background job scheduling توصیه میشود. ترکیب OOP و Asyncio modularity، readability و testability را افزایش میدهد. منابع رسمی، مثالهای open-source و آموزشهای پیشرفته برای یادگیری بیشتر مناسب هستند.
🧠 دانش خود را بیازمایید
آزمون دانش شما
درک خود از این موضوع را با سوالات کاربردی بسنجید.
📝 دستورالعملها
- هر سوال را با دقت بخوانید
- بهترین پاسخ را برای هر سوال انتخاب کنید
- میتوانید آزمون را هر چند بار که میخواهید تکرار کنید
- پیشرفت شما در بالا نمایش داده میشود