گاهی ممکن است تسک خیلی طولانی شده باشد و شما بخواهید آن را کنسل کنید. در این صورت میتوانید از متد cancel استفاده کنید.
import asyncio
async def download_file(file_name):
print(f'dowload {file_name} started')
await asyncio.sleep(6)
print(f'dowload {file_name} finished')
async def manage_downloads():
t1 = asyncio.create_task(download_file('test1.txt'))
seconds = 0
while not t1.done():
print('download still running')
await asyncio.sleep(1)
seconds += 1
if seconds == 5:
t1.cancel()
try:
await t1
except asyncio.CancelledError:
print('download cancelled!')
asyncio.run(manage_downloads())توضیح کد بالا:
- خط ۳ تا ۶: یک coroutine است که نام یک فایل را میگیرد و آن را دانلود میکند. در این coroutine اینطور شبیه سازی شده است که ۶ ثانیه زمان برای دانلود فایل لازم است.
- خط ۹: یک task میسازیم تا بتوانیم آن را به صورت async اجرا کنیم.
- خط ۱۱ تا ۱۷: یک حلقه را به مدت ۵ ثانیه اجرا میکنیم و بررسی میکنیم که در این ۵ ثانیه اگر تسک به پایان نرسیده بود با کدی که در خط ۱۷ نوشته شده است cancel شود.
- خط ۱۹ تا ۲۲: در صورتی که خط ۱۷ اجرا شود، خطای CancelError ایجاد میشود که در این قسمت آن را میگیریم.
البته بهتر است کد بالا را به شکل زیر بنویسیم
import asyncio
async def download_file(file_name):
print(f'dowload {file_name} started')
await asyncio.sleep(6)
print(f'dowload {file_name} finished')
async def manage_downloads():
t1 = asyncio.create_task(download_file('test.txt'))
try:
await asyncio.wait_for(t1, timeout=5)
except asyncio.CancelledError:
print('download cancelled!')
asyncio.run(manage_downloads())محافظت از یک تسک در برابر کنسل شدن
متد shield یک coroutie را از کنسل شدن محافظت میکند اما همچنان با رخ دادن timeout خطای TimeoutError خواهیم داشت. همچنین تسک از ادامه اجرا متوقف میشود که در صورت نیاز باید خودمان آن را مجدد ادامه دهیم.
import asyncio
async def download_file(file_name):
print(f'dowload {file_name} started')
await asyncio.sleep(6)
print(f'dowload {file_name} finished')
async def manage_downloads():
t1 = asyncio.create_task(download_file('test.txt'))
try:
await asyncio.wait_for(asyncio.shield(t1), timeout=5)
except asyncio.TimeoutError:
print('downloading takes too long but we ar working on it')
await t1
asyncio.run(manage_downloads())