Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decompose asyncio.run_forever() into parts to improve integration with other event loops #110771

Closed
freakboy3742 opened this issue Oct 12, 2023 · 1 comment · Fixed by #110773
Closed
Labels
topic-asyncio type-feature A feature request or enhancement

Comments

@freakboy3742
Copy link
Contributor

freakboy3742 commented Oct 12, 2023

Feature or enhancement

Proposal:

This is an admittedly niche use case, but it's one that we've hit in the development of Toga.

GUI toolkits all have event loops. If you want to use Python asyncio calls in a GUI app, it is necessary to make the GUI's event loop and Python's asyncio event loop co-exist.

This usually means writing a subclass of EventLoop that overrides run_forever() in some way. Either the inner while True: _run_once() loop of run_forever() needs to be modified to integrate the equivalent "run once" of the GUI's event loop; or the while True loop needs to be subverted entirely and _run_once() needs to be invoked regularly on the GUI's event loop.

However, the implementation of run_forever() makes this difficult to do without duplicating significant portions of the implementation of run_forever(). For example, Toga's Winforms asyncio integration involves duplicating the startup and shutdown of run_forever()

The fundamental structure of run_forever() is:

def run_forever():
    try:
        run_forever_setup()
        while True:
            run_once()
    finally:
        run_forever_cleanup()    

I propose that the implemenation of run_forever() be decomposed into exactly these parts - an initial setup, the actual loop, and a post-loop cleanup. This does not impact on the operation of ascynio itself, but it would allow Toga (and any other integrated asyncio loop) to automatically inherit any improvements that are made to the core event loop.

It is worth noting that CPython's own Winforms integration has a similar need. The implementation of run_forever() in ProactorEventLoop() needs to include additional setup and additional cleanup calls. Decomposing the base event loop would allow this additional setup and cleanup to be explcit.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

Informal in-person discussion at CPython core team sprint.

Linked PRs

@gvanrossum
Copy link
Member

Thanks! I think this (GUI event loop integration) was an originally intended use case, and there was talk of doing a Tkinter integration as an example, but it never panned out, and I stopped caring about Tkinter personally.

It was my understanding that most GUI integrations just run the asyncio event loop in a separate thread. I think it's exciting that Toga managed to do this integration right and that a feature request came out of it.

Could you propose a specific API? It shouldn't be hard to get rough consensus on that, and then you can start implementing. Or you could start with an implementation (so you're perhaps more sure that it actually works, etc.). Up to you.

@github-project-automation github-project-automation bot moved this from Todo to Done in asyncio Oct 13, 2023
gvanrossum pushed a commit that referenced this issue Oct 13, 2023
Effectively introduce an unstable, private (really: protected) API for subclasses that want to override `run_forever()`.
aisk pushed a commit to aisk/cpython that referenced this issue Feb 11, 2024
Effectively introduce an unstable, private (really: protected) API for subclasses that want to override `run_forever()`.
Glyphack pushed a commit to Glyphack/cpython that referenced this issue Sep 2, 2024
Effectively introduce an unstable, private (really: protected) API for subclasses that want to override `run_forever()`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-asyncio type-feature A feature request or enhancement
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants