برای اینکه چند تسک را همزمان با یکدیگر شروع و تمام کنید میتوانید از متد gather استفاده کنید.
import asyncio
async def download_file(file_name):
assert '%' not in file_name, "Bad file name!"
print(f'dowload {file_name} started')
await asyncio.sleep(2)
print(f'dowload {file_name} finished')
return file_name
async def manage_downloads():
t1 = asyncio.create_task(download_file('test1.txt'))
t2 = asyncio.create_task(download_file('text2.txt'))
res = await asyncio.gather(t1, t2)
print(res)
asyncio.run(manage_downloads())توضیح کد بالا:
- خط ۳ تا ۸: یک coroutine تعریف کردهایم که نام یک فایل را میگیرد و اگر کارکتر
%در نامش نداشت آن را دانلود میکند. - خط ۱۹ تا ۱۵: یک coroutine تعریف کردهایم که coroutine های دیگر را در خود اجرا میکند.
- خط ۱۴: در این قسمت با استفاده از
gatherهمزمان t1 و t2 را اجرا کردهایم.
- خط ۱۴: در این قسمت با استفاده از
تعامل با ارور ها
اگر نام فایل حاوی % باشد coroutine ارور میدهد. به تکه کد زیر توجه کنید:
import asyncio
async def download_file(file_name):
assert '%' not in file_name, "Bad file name!"
print(f'dowload {file_name} started')
await asyncio.sleep(2)
print(f'dowload {file_name} finished')
return file_name
async def manage_downloads():
t1 = asyncio.create_task(download_file('test.txt'))
t2 = asyncio.create_task(download_file('text%.txt'))
res = await asyncio.gather(t1, t2)
print(res)
asyncio.run(manage_downloads())خروجی این کد شبیه زیر خواهد بود:
dowload test.txt started
Traceback (most recent call last):
File "/home/username/workspace/concurrency/01.py", line 17, in <module>
asyncio.run(manage_downloads())
File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/home/username/workspace/concurrency/01.py", line 14, in manage_downloads
res = await asyncio.gather(t1, t2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/username/workspace/concurrency/01.py", line 4, in download_file
assert '%' not in file_name, "Bad file name!"
^^^^^^^^^^^^^^^^^^^^
AssertionError: Bad file name!
با کمی تغییر در کد بالا میتوان به کد زیر رسید که به این شکل خطا نمیدهد.
import asyncio
async def download_file(file_name):
assert '%' not in file_name, "Bad file name!"
print(f'dowload {file_name} started')
await asyncio.sleep(2)
print(f'dowload {file_name} finished')
return file_name
async def manage_downloads():
t1 = asyncio.create_task(download_file('test.txt'))
t2 = asyncio.create_task(download_file('text%.txt'))
res = await asyncio.gather(t1, t2, return_exceptions=True)
print(res)
asyncio.run(manage_downloads())خروجی این کد شبیه به زیر خواهد بود:
dowload test.txt started
dowload test.txt finished
['test.txt', AssertionError('Bad file name!')]