Сравнение async и ThreadPoolExecutor в Python
Асинхронная обработка async
В async переключение выполнения на уровне CPU происходит в момент выполнения
await.
Но чтобы можно было вызвать
await, сам код должен поддерживать async.
Например, если вы хотите делать запись в PostgreSQL через async, то придется использовать
asyncpg.
То есть для тех операций, которые поддерживают async, можно реализовать асинхронную обработку с помощью async.
Параллельная обработка ThredPoolExcutorThredPoolExcutor имеет смысл использовать в тех случаях, когда:
* код не поддерживает async
* или вы хотите распараллелить выполнение, минимально переписывая существующий код.
Тестовый кодАсинхронная обработка async:
import asyncio
import time
from icecream import ic
async def io_task(name):
print(f"{name} start")
await asyncio.sleep(3) # ожидание неблокирующего I/O
print(f"{name} end")
async def main():
start = time.time()
await asyncio.gather(io_task("A"), io_task("B"), io_task("C"))
print(f"elapsed: {time.time() - start:.3f}")
ic()
asyncio.run(main())
ic()
# Результат выполнения
ic| main_async.py:19 in <module> at 22:06:11.408
A start
B start
C start
A end
B end
C end
elapsed: 3.001
ic| main_async.py:21 in <module> at 22:06:14.412
Параллельная обработка ThredPoolExcutor:
import time
from concurrent.futures import ThreadPoolExecutor
from icecream import ic
def io_task(name):
print(f"{name} start")
time.sleep(3) # блокирующий I/O
print(f"{name} end")
ic()
start = time.time()
with ThreadPoolExecutor(max_workers=3) as executor:
executor.submit(io_task, "A")
executor.submit(io_task, "B")
executor.submit(io_task, "C")
print(f"elapsed: {time.time() - start:.3f}")
# Результат выполнения
ic| main_ThreadPoolExcutor.py:13 in <module> at 22:07:03.543
A start
B start
C start
C end
B end
A end
elapsed: 3.003
Вывод: В случаях, когда требуется блокирующая обработка вроде
time.sleep[1], имеет смысл использовать ThredPoolExcutor.
Когда же нужна неблокирующая обработка, как в случае с
asyncio.sleep, лучше использовать async.
👉
@PythonPortal