Skip to content

QEventLoop confuses asyncio's get_running_loop #72

@mdickinson

Description

@mdickinson

QEventLoop.__init__ does asyncio.events._set_running_loop(self), which has the effect that asyncio.get_running_loop() then returns an event loop.

For cases where a QEventLoop is being created within an already running asyncio event loop, this may be the right thing to do; I'm not sure. In our use-case, we're creating the QEventLoop before entering the asyncio event loop, so this causes some confusion.

Additionally, after the event loop has exited, asyncio.get_running_loop() should also be raising RuntimeError. Instead, it's returning the QEventLoop, even though there's no running loop at that point.

This is particularly affecting our unit tests: after a unit test that's using the QEventLoop we want to set asyncio back to a state that's more-or-less what happens before the QEventLoop was created. For that I'm doing:

        if asyncio.get_event_loop().is_closed():
            asyncio.set_event_loop(asyncio.new_event_loop())

But this silently fails to work (tested on Python 3.8): asyncio.get_event_loop continues to return the QEventLoop, since that event loop is still registered as running.

In case others run into the same issue: we're working around this in our own code by using the set_running_loop=False option when creating the QEventLoop, and then wrapping calls to run_forever as follows:

asyncio.events._set_running_loop(event_loop)
try:
    event_loop.run_forever()
finally:
    asyncio.events._set_running_loop(None)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions