Uh oh!
There was an error while loading. Please reload this page.
Replace Tornado with AnyIO - #1079
Conversation
maartenbreddels
commented
Jan 25, 2023
+1 on AnyIO, they seem to have all the missing primitives needed for doing asyncio+threaded work, seems like a solid project. |
dhirschfeld
commented
Jan 25, 2023
As a |
I must point out that using blocking portals in this manner will block the original event loop, preventing any other tasks from running until the blocking call is complete. What should also be taken into account is any Protocols and tasks launched from the nested loop, which will also stop functioning once the blocking call completes. As a former Java programmer, I recall that Java used a similar approach to solve this problem, but there the nested event loop was able to process events from the parent loop. |
davidbrochart
commented
Jan 25, 2023
Thanks for the feedback @agronholm. |
agronholm
commented
Jan 25, 2023
Yeah, sorry, it's a rather large and complex PR so I haven't read through it, so I just made assumptions based on your other posts. So are you creating one-off event loops for running async callables from sync functions? Or do you have a lingering, shared event loop thread running in the background? Either way, thread safety is the biggest problem. One of the main selling points of async is that you can reliably determine where you can mutate shared objects safely (without explicit locks) since all other code is suspended until the next yield point. Those guarantees go out the window when two simultaneously running event loops share memory.
Technically there is no such thing as an AnyIO event loop 😄 |
davidbrochart
commented
Jan 25, 2023
Yes, the control thread runs for the whole duration of the kernel process, so we're not creating lots of event loops. |
ccordoba12
commented
Jan 25, 2023
Just a quick note to say that this seems significant enough to mark it for IPykernel 7. |
davidbrochart
commented
Jan 25, 2023
Yes, I agree. It also requires |
7b04678 to
3cb5832Compare08a3baa to
b2fe7c1Comparedavidbrochart
commented
Feb 15, 2023
I'd like to merge this PR and update downstream projects in other PRs. |
davidbrochart
commented
Mar 13, 2024
I'm looking into it, but at first sight this code was working in my first commit: fromthreadingimportThreadfromtimeimportsleepdefthread_target():
foriinrange(5):
print(i, end='', flush=True)
sleep(0.25)
Thread(target=thread_target).start()It successfully prints |
agronholm
commented
Mar 13, 2024
Is |
davidbrochart
commented
Mar 13, 2024
No, but yes we might replace all this complicated way of communicating between threads using ZMQ pipes with AnyIO's functions. |
davidbrochart
commented
Mar 13, 2024
Doesn't look good 😄 |
davidbrochart
commented
Mar 13, 2024
@blink1073 For me even without c1dce80 a lot of tests hang locally, for instance tests related to cell interrupt and in-process kernels. It seemed to be the case in the CI too. |
davidbrochart
commented
Mar 19, 2024
davidbrochart
commented
Mar 22, 2024
So currently the remaining failing tests are in |
blink1073
commented
Mar 22, 2024
I'd say let's skip those for now, and then merge and iterate. |
davidbrochart
commented
Mar 22, 2024
One remaining failing test on Windows: |
blink1073
commented
Mar 22, 2024
Sounds right to me |
blink1073
commented
Mar 22, 2024
Thanks @davidbrochart! |
davidbrochart
commented
Mar 22, 2024
Thank you @blink1073 ! |
rayosborn
commented
Oct 26, 2024
Is a fix for the in-process kernel test failure planned. before the release of v7? |
References
Supersedes #876.
Closes#656.
IPykernel should not depend on a web server. It uses Tornado as an async framework, but modern Python has better solutions, including standard
asyncio. Tornado's use in ipykernel involves using a lot of queues and creates complexity that makes maintenance or improvements to the code base harder.Structured concurrency as introduced by Trio is gaining a lot of traction. AnyIO brings structured concurrency on top of
asyncioand acts as an abstraction layer which allows to choose a concurrency backend, such asasyncioortrio. Major projects have switched to AnyIO, including FastAPI.This PR is still a work in progress. I have disabled some tests, like the ones for in-process kernels. Also, I think we should re-think event-loop integration (maybe using Trio's approach). But I would like to get feedback from the community and discuss how we can move forward with these changes.
cc @SylvainCorlay@JohanMabille@minrk@ccordoba12
Code changes
The dependency to Tornado is dropped, in favor of AnyIO. This means that instead of using ZMQStream with
on_recvcallbacks, we use async/await everywhere.Using AnyIO in the main thread event loop gives us Trio support for free in the user code. It is currently disabled until we get AnyIO support in pyzmq, or decide to process shell messages in a separate thread, which might be needed for sub-shells anyway.
User-facing changes
The goal is to have no user-facing change. However, I have identified the following ones:
stdout,stderr) is improved as there is no delay anymore.Backwards-incompatible changes
shell_socket).async, including theKernel.startmethod.Kernel.stop(thread-safe) method.