Три вещи которые обязательно нужны в production async коде.
asyncio.timeout() — таймауты без боли (Python 3.11+)
import asyncio
async def slow_operation():
await asyncio.sleep(10)
async def main():
try:
async with asyncio.timeout(3.0): # 3 секунды максимум
await slow_operation()
except TimeoutError:
print("Превысили таймаут")
До Python 3.11 использовался asyncio.wait_for():
try:
result = await asyncio.wait_for(slow_operation(), timeout=3.0)
except asyncio.TimeoutError:
print("Таймаут")
CancelledError — отмена задач
async def worker():
try:
while True:
await do_work()
except asyncio.CancelledError:
await cleanup() # освобождаем ресурсы
raise # ВАЖНО: всегда перебрасываем CancelledError
async def main():
task = asyncio.create_task(worker())
await asyncio.sleep(5)
task.cancel() # отправляем CancelledError в task
try:
await task
except asyncio.CancelledError:
print("Задача отменена корректно")
Правило: в except CancelledError всегда делай raise. Иначе задача не завершится корректно.
Graceful shutdown — красивое завершение
import asyncio, signal
async def main():
loop = asyncio.get_running_loop()
stop = asyncio.Event()
def handle_signal():
print("Получен SIGINT, завершаем...")
stop.set()
loop.add_signal_handler(signal.SIGINT, handle_signal)
loop.add_signal_handler(signal.SIGTERM, handle_signal)
# Основная работа
tasks = [asyncio.create_task(worker(i)) for i in range(5)]
await stop.wait() # ждём сигнала
# Отменяем все задачи
for task in tasks:
task.cancel()
# Ждём завершения с cleanup
await asyncio.gather(*tasks, return_exceptions=True)
print("Завершено чисто")
asyncio.run(main())
return_exceptions=True в gather() важно: без него первый CancelledError прервёт ожидание остальных задач.
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!