در برنامهنویسی غیرهمزمان با استفاده از asyncio
در پایتون، گاهی نیاز است که یک task (وظیفه) را قبل از تکمیل متوقف کنیم. برای این کار، از متد cancel
استفاده میشود که به شما اجازه میدهد اجرای یک task را به طور ایمن و کنترلشده متوقف کنید.
استفاده از cancel
متد cancel
برای متوقف کردن یک task در asyncio
استفاده میشود. زمانی که این متد را فراخوانی میکنید، یک استثنا (asyncio.CancelledError
) در task هدف ارسال میشود که میتوان آن را مدیریت کرد تا منابع به درستی آزاد شوند یا عملیاتهای پاکسازی انجام شوند.
نحوه استفاده
در اینجا مثالی برای استفاده از cancel
در asyncio
آورده شده است:
import asyncio
async def my_coroutine():
try:
print("Coroutine started")
await asyncio.sleep(10) # یک عملیات طولانی
print("Coroutine ended")
except asyncio.CancelledError:
print("Coroutine was cancelled")
# انجام عملیاتهای پاکسازی
raise
async def main():
task = asyncio.create_task(my_coroutine())
await asyncio.sleep(1) # صبر برای مدت کوتاه
task.cancel() # لغو task
try:
await task # منتظر task باشید تا لغو شود
except asyncio.CancelledError:
print("main: Task has been cancelled")
asyncio.run(main())
توضیحات
تعریف coroutine با مدیریت استثنا:
my_coroutine
: یک coroutine که منتظر 10 ثانیه میماند. اگر لغو شود، asyncio.CancelledError
را مدیریت میکند و پیام مناسبی چاپ میکند.
ایجاد و لغو task:
task = asyncio.create_task(my_coroutine())
: ایجاد یک task برای اجرایmy_coroutine
.await asyncio.sleep(1)
: صبر برای 1 ثانیه قبل از لغو task.task.cancel()
: لغو task.await task
: منتظر میمانیم تا task لغو شده کامل شود و استثنا را مدیریت میکنیم.
نکات مهم
- مدیریت
CancelledError
: هنگام لغو یک task،asyncio.CancelledError
در آن task ارسال میشود. باید این استثنا را مدیریت کنید تا مطمئن شوید منابع به درستی آزاد میشوند. - پاکسازی: اگر task شامل عملیاتهایی باشد که نیاز به پاکسازی دارند (مثل بستن فایلها یا اتصالات شبکه)، باید این عملیاتها را در بلوک
except
انجام دهید. - لغو ایمن: همیشه پس از لغو یک task، با استفاده از
await task
منتظر بمانید تا task به درستی پایان یابد.
مثال پیچیدهتر
در یک مثال پیچیدهتر، میتوانیم نشان دهیم که چگونه چندین task را لغو کنیم:
import asyncio
async def worker(name, duration):
try:
print(f"Worker {name} started")
await asyncio.sleep(duration)
print(f"Worker {name} finished")
except asyncio.CancelledError:
print(f"Worker {name} was cancelled")
raise
async def main():
tasks = [
asyncio.create_task(worker("A", 3)),
asyncio.create_task(worker("B", 5)),
asyncio.create_task(worker("C", 7)),
]
await asyncio.sleep(4) # صبر برای مدت کوتاه
for task in tasks:
task.cancel() # لغو همه taskها
await asyncio.gather(*tasks, return_exceptions=True) # مدیریت لغو همه taskها
asyncio.run(main())
در این مثال، سه task با زمانهای مختلف ایجاد میشوند و بعد از 4 ثانیه، همه آنها لغو میشوند. خروجی نشان میدهد که taskها به درستی لغو شده و پیامهای مربوط به لغو چاپ میشوند. در نهایت استفاده از cancel
در asyncio
ابزاری قدرتمند برای مدیریت taskها و لغو آنها به صورت ایمن و کنترلشده است. با استفاده از این قابلیت، میتوانید برنامههای غیرهمزمان پیچیده و قابل اطمینانتری بنویسید که به درستی با شرایط لغو و پاکسازی منابع مقابله میکنند.