Summary#
Python 3.13은 asyncio.TaskGroup에서 자식 작업의 내부 실패와 부모 작업에 대한 외부 취소가 동시에 발생할 때의 처리를 개선했다. 핵심 계약은 그룹이 종료 절차에 사용하는 내부 취소를 외부 취소와 혼동하지 않고, Task.cancelling()에 나타나는 취소 요청 횟수를 보존하는 것이다. (docs.python.org)
Key Points#
- 자식 작업이
CancelledError이외의 예외로 실패하면TaskGroup은 나머지 작업을 취소하고 기다린 뒤, 해당 예외들을ExceptionGroup또는BaseExceptionGroup으로 올린다. 그룹 종료를 깨우기 위한 내부 취소는 이 실패 처리의 일부이지, 외부에서 들어온 취소 요청과 같은 것으로 취급해서는 안 된다. (docs.python.org) - 외부 취소와 예외 그룹이 경합하면, 그룹은 예외 그룹을 올리면서 부모 작업에 다시
cancel()을 호출한다. 따라서 취소 신호가 사라지지 않고 다음await에서CancelledError가 발생할 수 있다. 이는 예외 그룹과 취소 예외가 반드시 동시에 전파된다는 뜻은 아니다. (docs.python.org) - 중첩 그룹이 동시에 실패하면, 안쪽 그룹이 먼저 자신의 예외를 처리하고, 바깥 그룹은 별도의 취소 신호를 받아 자신의 예외를 처리해야 한다. Python 3.13 변경 설명은 이전에 안쪽 그룹이 취소를 삼켜 바깥 그룹이 멈출 수 있었던 경합을 명시한다. (docs.python.org)
- 회귀 검증은 자식 실패와 외부
cancel()을 경합시키고, 중첩 그룹 각각의 예외 처리 완료 여부와 부모의cancelling()횟수, 후속await에서의 취소 전달을 함께 확인하는 방향이 적절하다. 이는 위 문서화된 계약에서 도출한 검증 제안이다. (docs.python.org)
Cautions#
cancelling()은 취소 요청의 횟수를 나타내며, 작업이 이미cancelled()상태라는 뜻은 아니다. 특정 경합에서 기대할 정확한 숫자는 최초 취소 요청 횟수와 테스트 구성에 따라 정해야 한다. (docs.python.org)- 자식 코루틴이
CancelledError를 삼키거나 사용자 코드가uncancel()을 임의로 호출하면 구조화된 동시성의 취소 동작이 달라질 수 있다. 이 초안은 그런 코드에 대해서까지 전파를 보장하지 않는다. (docs.python.org) - 이 초안은 공식 문서와 Python 3.13 변경 설명에 근거한다. 특정 회귀 테스트의 실행 결과나 모든 3.13 패치 릴리스에서의 동작을 독립적으로 확인한 것은 아니다. (docs.python.org)
Sources#
- https://docs.python.org/3.13/library/asyncio-task.html
- https://github.com/python/cpython/blob/main/Doc/whatsnew/3.13.rst?plain=1
Sagwan Revalidation 2026-10-21T21:20:47Z#
- verdict:
ok - note: Python 3.13의 변경 사항과 취소 처리 주의점이 구분되어 있어 재사용 가능하다.