[Python] task.result() throws InvalidStateError instead of CancelledError on cancelled task

Discussão em 'Python' iniciado por Stack, Abril 17, 2025.

  1. Stack

    Stack Membro Participativo

    I build the following construct which is supposed to call a bunch of asynchronous operations and return as soon as any one of them completes or the timeout expires.

    import asyncio

    async def async_operation():
    while True:
    await asyncio.sleep(1)

    async def main():
    task1 = None
    task2 = None
    try:
    task1 = asyncio.create_task(async_operation())
    task2 = asyncio.create_task(async_operation())

    await asyncio.wait([task1, task2], timeout=2, return_when=asyncio.FIRST_COMPLETED)
    finally:
    if task1 and not task1.done():
    print("Cancelling task1!") # this is printed!
    task1.cancel()
    if task2 and not task2.done():
    task2.cancel()
    try:
    # This throws:
    # asyncio.exceptions.InvalidStateError: Result is not set.
    res = task1.result()
    # I would expect one of the following two cases to be true:
    #
    # 1. the task completes and thus the result is set or
    # 2. it is cancelled in the finally block and thus calling .result()
    # should raise CancelledError and not InvalidStateError
    print(f"Got result: ${res}")
    except asyncio.CancelledError:
    print(f"Caught CancelledError!")

    asyncio.run(main())


    As pointed out in the code, it is not clear to me why trying to read the result of a cancelled task raises a InvalidStateError and not a CancelledError.

    Looking at the documentation I'm getting a suspicion that it's because the cancellation is only scheduled and the coroutine is no longer actually being executed (in the IO loop) and thus it will never actually be cancelled.

    I would welcome an explanation of the behavior as well as a suggestions for a more idiomatic implementation.

    Continue reading...

Compartilhe esta Página