This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Asyncio breaks coroutine finalization process
Type: behavior Stage: resolved
Components: asyncio Versions: Python 3.7, Python 3.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: and800, asvetlov, yselivanov
Priority: normal Keywords:

Created on 2018-07-09 14:01 by and800, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (4)
msg321321 - (view) Author: Andriy Maletsky (and800) * Date: 2018-07-09 14:01
Source: https://stackoverflow.com/q/51245011/6275324

Asyncio somehow breaks coroutine finalization. I believe there may be a bug in C implementation (_asyncio) of tasks or futures. Reproducible within version 3.7.0@python:3.7 docker container.

Consider this example (except and finally blocks will never execute):


import asyncio

async def work():
    try:
        print('started working')
        await asyncio.sleep(3600)
    except BaseException as e:
        print('caught ' + str(type(e)))
    finally:
        print('finalization completed')

async def stopper():
    await asyncio.sleep(5)
    loop.stop()

loop = asyncio.get_event_loop()
loop.create_task(work())
loop.create_task(stopper())
loop.run_forever()



And there is asyncio-free piece of code, which works properly, catching GeneratorExit, thrown by coro destructor:


import asyncio

async def work():
    try:
        print('started working')
        await asyncio.sleep(3600)
    except BaseException as e:
        print('caught ' + str(type(e)))
    finally:
        print('finalization completed')

coro = work()
coro.send(None)
del coro
msg321323 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-07-09 15:22
There's no bug here. `loop.stop()` simply stops the loop, all running tasks are just paused. You can re-run the same loop, and the `work()` task will resume.

In other words, `loop.stop()` does not trigger task cancellation, therefore it does not throw in any exceptions into the `work()` task.
msg321325 - (view) Author: Andriy Maletsky (and800) * Date: 2018-07-09 15:57
I meant that my example is a complete python script, and after `loop.run_forever()` the interpreter stops. So I expected every python object to be destructed on interpreter shutdown, but coro's `close()` is not called.

To make example more practical, let's change `loop.stop()` to `raise KeyboardInterrupt()`. Program stops without calling `close()`
msg321329 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-07-09 16:07
> To make example more practical, let's change `loop.stop()` to `raise KeyboardInterrupt()`. Program stops without calling `close()`

Try to use the new `asyncio.run()` function (in Py 3.7)
History
Date User Action Args
2022-04-11 14:59:02adminsetgithub: 78255
2018-07-09 16:07:50yselivanovsetmessages: + msg321329
2018-07-09 15:57:40and800setmessages: + msg321325
2018-07-09 15:22:59yselivanovsetstatus: open -> closed
resolution: not a bug
messages: + msg321323

stage: resolved
2018-07-09 14:01:52and800create