در برنامهنویسی غیرهمزمان با asyncio در پایتون، await و create_task دو رویکرد مختلف برای اجرای coroutines هستند که هر کدام کاربردهای خاص خود را دارند. در اینجا تفاوت این دو و نحوه استفاده از آنها به همراه مثالی توضیح داده میشود.
await چیست؟
زمانی که از await استفاده میکنید، اجرای coroutine فعلی به صورت موقت متوقف میشود تا coroutine مورد انتظار تکمیل شود. این روش برای اجرای ترتیبی عملیاتهای غیرهمزمان مناسب است.
create_task چیست؟
asyncio.create_task یک coroutine را به یک task تبدیل میکند و آن را برای اجرا در پسزمینه به رویداد لوپ میسپارد. این روش به شما امکان میدهد که چندین task به صورت همزمان (parallel) اجرا شوند.
تفاوتها
- await: اجرای coroutine فعلی را متوقف میکند تا coroutine مورد انتظار تکمیل شود.
- create_task: اجرای coroutine فعلی را متوقف نمیکند، بلکه coroutine جدید را به صورت همزمان اجرا میکند.
مثال
در این مثال، دو coroutine تعریف میکنیم که هر کدام به مدت متفاوتی به حالت انتظار میروند. سپس از await و create_task استفاده میکنیم تا تفاوتها را نشان دهیم.
import asyncio
async def coro1():
print("coro1 started")
await asyncio.sleep(2)
print("coro1 ended")
async def coro2():
print("coro2 started")
await asyncio.sleep(1)
print("coro2 ended")
# استفاده از await
async def main_await():
await coro1()
await coro2()
# استفاده از create_task
async def main_create_task():
task1 = asyncio.create_task(coro1())
task2 = asyncio.create_task(coro2())
await task1
await task2
# اجرای مثال با await
print("Running with await:")
asyncio.run(main_await())
# اجرای مثال با create_task
print("\nRunning with create_task:")
asyncio.run(main_create_task())
توضیحات
تابع coro1 و coro2:
- coro1: این coroutine با چاپ یک پیام شروع میشود، سپس به مدت 2 ثانیه به حالت انتظار میرود، و در نهایت یک پیام دیگر چاپ میکند.
- coro2: این coroutine با چاپ یک پیام شروع میشود، سپس به مدت 1 ثانیه به حالت انتظار میرود، و در نهایت یک پیام دیگر چاپ میکند.
تابع main_await:
- await coro1(): اجرای coro1 را منتظر میماند تا تکمیل شود.
- await coro2(): بعد از تکمیل coro1، coro2 را اجرا و منتظر میماند تا تکمیل شود.
- در این حالت، coro1 و coro2 به صورت ترتیبی اجرا میشوند.
تابع main_create_task:
- task1 = asyncio.create_task(coro1()): coro1 را به یک task تبدیل کرده و برای اجرا به رویداد لوپ میسپارد.
- task2 = asyncio.create_task(coro2()): coro2 را به یک task تبدیل کرده و برای اجرا به رویداد لوپ میسپارد.
- await task1: منتظر میماند تا task1 (که همان coro1 است) تکمیل شود.
- await task2: منتظر میماند تا task2 (که همان coro2 است) تکمیل شود.
- در این حالت، coro1 و coro2 به صورت همزمان اجرا میشوند.
خروجی
خروجی برای main_await:
Running with await:
coro1 started
coro1 ended
coro2 started
coro2 ended
خروجی برای main_create_task:
Running with create_task:
coro1 started
coro2 started
coro2 ended
coro1 ended
در اجرای main_create_task، مشاهده میکنید که coro1 و coro2 به صورت همزمان شروع میشوند و coro2 که زمان انتظار کمتری دارد، زودتر به پایان میرسد. این نشان میدهد که چطور create_task به ما امکان میدهد تا coroutines را به صورت همزمان اجرا کنیم.