Skip to content

What to do about calls to get_event_loop() in Trio context when no loop is active? #68

Open
@oremanj

Description

@oremanj

Many asyncio objects (such as asyncio.Lock) call asyncio.get_event_loop() in their constructor, if no loop was passed. Much asyncio-using code seems to assume that such objects can be created when no loop is running, and that they'll attach themselves to the loop that winds up running later.

This pattern works fine (at least post #66) outside of Trio context. get_event_loop() will delegate to the installed event loop policy; if no custom policy has been installed, it will return the event loop for the current thread, creating it as a SyncTrioEventLoop if necessary.

Inside Trio context, though, we currently expect every event loop to be a TrioEventLoop bound to an async with open_loop() block somewhere. If no TrioEventLoop has yet been created, what can we do?

lock = asyncio.Lock()
async with trio_asyncio.open_loop():
    [use lock here]

which seems like it might still break some use cases.

  • Possible change: create a new TrioEventLoop, set the current_loop cvar to use it, and teach open_loop() to manage the existing ambient loop instead of creating a new one if an existing ambient loop exists and isn't running. (It should still be possible to nest open_loop() calls to get two different loops with different scoping behavior if the outer loop is running.) This seems like it may have the closest behavior to non-trio-enabled asyncio: you can still set things up against a loop when it's not running, but your callbacks won't, like, run.
  • Possible change: create a new TrioEventLoop and start running it in a system task. I think this is strictly inferior to the previous bullet but it was the first thing I thought of so I mention it for completeness, in case there's some reason I'm missing why it would be better. The hazard is that in the above example, Lock would be in the global loop which is not the same loop as everything inside the async with block. And while I can't immediately think of a reason this wouldn't work, if it breaks it's going to be really confusing to understand.

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