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
Add simple web loop #1158
Add simple web loop #1158
Conversation
d0240e6
to
1adf37e
Compare
I also don't have a good understanding of the tradeoffs, but I would tend to go with this simpler solution first, if it's sufficient for most use cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, I also like simpler solution!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks reasonable (from someone who hasn't worked much with asyncio). A few minor mostly docstring related comments below. Also please add a changelog entry.
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
FYI, you can add all review suggestions in one commit/batch if you do it from the "Files changed" tab. |
Thanks for the tip. |
I also copied more docstrings from |
Also could you please add the added classes to https://github.com/iodide-project/pyodide/blob/master/docs/usage/api-reference.md and check that that the corresponding documentation is rendering fine? |
I guess it's rendering fine, but it doesn't look great. The autodoc adds a lot of methods from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need a changelog entry
Oops, will add it. |
I also added a separate entry for #880. |
Seems like |
So loop = events.get_running_loop()
task = loop.create_task(coro) whereas if coroutines.iscoroutine(coro_or_future):
if loop is None:
loop = events.get_event_loop()
task = loop.create_task(coro_or_future) The difference in behaviors occurs only when there is no currently running event loop. In that case, |
Well automatically starting the event loop causes trouble with one CPython test. I guess I'll revert the |
OK, thanks for investigating. |
I'm not sure if I should be commenting here or opening a new issue. But I think my question is pretty closely related to this, so I'll put it here. I'm building a web page where students can edit Python code, then click "Run" to run it in pyodide. I started with all of this running in the main browser thread, which worked pretty well. As part of this, I added some glue code so that However, when pyodide runs in the main thread, my code cannot update the display (e.g., show output), and controls are locked, so I can't have a "Stop" button to kill Python code that runs out of control. So I am working on a version where pyodide runs as a web worker. I've got that working for most of what I want, except for getting input back from the user. Specifically, I send messages to from the worker to the main browser thread to launch the prompt, then send a message back from the main thread to the worker with the result. The problem is, I can't see any way to get the Python code to wait for the return message. I think that may be possible in general, if I write all-async code. The problem is, the incoming code is not written for an async environment (e.g., the students will use I tried using I'm now thinking about using shared memory between the browser thread and the worker, then running a busy loop in the worker that polls for a response via the shared memory (since I don't think sleep is possible). But I'd rather not use such a narrow solution and peg the processor that way. So I just wanted to check, is there currently any path to get synchronous Python code to wait for a JavaScript promise or async function? |
This is a simple webloop aimed at enabling asyncio support as simply and painlessly as possible. It defers all work to the browser using
setTimeout
. Because the browser event loop has no lifecycle (well no lifecycle visible from javascript), there is no reason for us to have a lifecycle either, and all lifecycle methods are dummied out. I didn't implementcall_exception_handler
or it's friends at all because they are normally invoked during the teardown of an event loop, but we never do teardown.Also, like in #958,
run_forever
andrun_until_complete
cannot block because we only have one thread.I think this event loop will have better performance than the one in #958. It may well have worse compatibility, but I stole @oeway's test suite so any difference in compatibility is not caught by the tests. I'm not really sure what the tradeoffs involved are, there might be reason to have a simple event loop with better performance for normal purposes and a more complicated event loop with worse performance but with better compatibility.
Anyways I think this is a good starting point for now and if there is need for something more elaborate we can find out and deal with that down the road. Many thanks to @oeway for his work on this, I used a lot of his ideas here.
After we add an event loop, the only thing left that we need for asyncio support is to implement
then
on pyproxies for awaitable python objects, so that apyproxy
of a python awaitable is a javascript awaitable.