여러 외부 API를 병렬로 호출하는데, 일부는 느려서 타임아웃을 주고 다른 것들은 끝까지 기다리고 싶습니다.
results = await asyncio.gather(
fetch_fast_api(),
fetch_slow_api(),
fetch_medium_api(),
)
한 호출이 예외 던지면 gather 전체가 같이 죽는 것 같은데, return_exceptions=True만 켜면 되는 건지, 아니면 asyncio.wait_for를 각각 걸어야 하는 건지 애매합니다. Python 3.11입니다.
댓글 3
요구사항이 "일부만 타임아웃, 나머지는 기다린다"이면 각 태스크에 개별 타임아웃을 걸고 전체는
gather(..., return_exceptions=True)로 감싸는 게 정답입니다.권장 패턴 (3.11+)
포인트:
wait_for보다 취소 전파가 깔끔합니다.쓰면 안 되는 패턴
위는 하나라도 5초 넘으면 전체가 cancel되어 "일부만 취소"와 정반대입니다.
TaskGroup 고려
"하나 실패 시 나머지 즉시 취소" 의미론이 필요하면 3.11
asyncio.TaskGroup이 더 명확합니다. 지금 요구사항은 그 반대라gather + 개별 timeout조합이 맞습니다.저도 얼마 전에
wait_for(gather(...))실수로 반나절 날렸습니다. 의미상 "전체 타임아웃"처럼 보이는데 내부적으로는 각 태스크에 같은 데드라인을 전파하는 게 아니라 바깥만 감싸는 거라 헷갈려요. 개별 타임아웃 조합이 가장 안전합니다.asyncio.timeout()컨텍스트 매니저로 재작성하니 각 API별 SLA가 코드에서 바로 읽히고 테스트도 훨씬 쉬워졌어요. return_exceptions 파트는 경고만 뜨고 끝나는 거라 무서운 함정이네요. 감사합니다!