-
-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
implement "Async exec" #78797
Comments
Hi, This is an issue, prompted by twitter (https://twitter.com/Mbussonn/status/1038866329971961859) and by the imminent release of IPython 7.0 that provides an async REPL to discuss the introducion of something I'll call "Async exec", the exact form can vary, but I believe the name si relatively self explanatory. The short description would be to allow something akin to For example IPython 7.0 (current master branch) allow the following:
Sleep is here and example, but you can play with aoihttp, asks, and other library and it "just works". Alternatively when using IPython via Jupyter, you can also schedule background tasks that will execute in the currently running loop. To reach this, we had to work around a large number of roadblock, and there is a number of missing pieces (or things especially prevented) in core Python we had to work around. To see how we did that see ipython/ipython#11265 The core being if we have a block of async code like During the development and test of the above feature of IPython here are some of the challenges we got with top-level async code.
It make sens for a module for this to be invalid syntax, but not in a repl.
So far in IPython we have to carry-over and recompute whether to actually run the compiled byte code in classical
Allow new AIO library like trio/curio/... to use this. Note that despite both using IPython, the above cover 2 use cases.
AFAICT, this would also be of potential use for other REPL (Xonsh, Bpython). I'm happy to give more details, but I think that's a enough of a broad overview, as we should be releasing this in IPython in a few days/week, we will likely have further feedback from a wider range of users that can inform the design. |
I think the first thing is to add async "modes" to compile: in particular "async-exec" and "async-single". These would be like the current "exec" and "single" modes respectively, except that they act like the code is inside an "async def", so "await" is allowed, and executing the resulting code object produces a coroutine object that has to be iterated to actually run the code. I guess we might want "async-eval" too just for completeness, though I'm not currently aware of any use cases for that. A utility to check whether an AST requires async mode should be fairly straightforward. So if you want to choose on the fly, you would do:
Once you have a code object, I think it's too late: if you use "async-exec" mode to compile a code object that doesn't actually use 'await', then it should still return a coroutine object that needs iterating, etc., just like an 'async def' that has no 'await' in it. So if you want to do this check, the AST phase is the time to do it. Maybe ast.is_ast_async(ast_obj)?
This seems like a separate problem from the async stuff... I'm curious to hear how what distinction you want to make between 'exec' and a new 'multi-single' (?) mode, but maybe that should be a new issue? |
Mell, in classical In IPython[1] we also have to dance to trigger the display hook in a multi-line context by executing each top-level node one by one. So while we are designing a new |
Here is one case we forgot in IPython apparently : In [1]: x = 1 This is not detected as a syntax error, but considered as asyn, we took an approach that prefer false positive (try to run invalid syntax as async) than false negative (reject valid async-code). Add this to the test suite for this feature. |
So through time our heuristic to check wether a code should be async or not grew: There also seem to be some code that uses I'm thinking of submitting a talk at PyCon to explain what we've discover so far in IPython. |
indeed adding async flag to compile and providing some 'aexec' is a very good idea ! *an async repl is really usefull when stuck with a threadless python* ( specific engines, or emscripten cpython ) "top-level async is invalid syntax" : First raising an exception "top level code is async" and allowing user to get source code from exception would maybe a nice start to an async repl. |
In IPython we use Also have a look at https://github.com/ipython/ipython/blob/320d21bf56804541b27deb488871e488eb96929f/IPython/core/interactiveshell.py#L121-L150 Seem to be equivalent to what you aare trying to do with updating your locals here https://github.com/pmp-p/aioprompt/blob/93a25ea8753975be6ed891e8d45f22db91c52200/aioprompt/__init__.py#L78-L94 It just sets the function to not create a new local scope |
i already use prompt_toolkit on droid as it uses concurrent futures for completion and threads are allowed on that platform, and yeah it is quite good. but no way to use it on emscripten where cpython is 100% async ( it uses dummy_threading to load asyncio ). best you can do is fill an history buffer with the indented input, eval the whole thing when it's done with PyRun_SimpleString. having cpython storing code until sync/async path can be choosen could save a lot of external hacks with minimal impact on original repl loop, unless somebody is willing to make it *fully* async ( i know i can't ). The original repl input loop is really not made for async and i don't know if Sylvain Beuclair's work on "emterpreted" cpython covers also python3. thx for the pointers anyway and your article on async and ast was inspiration. |
You totally should! Or actually there are two options to think about: you can submit a general talk, or submit a talk to the language summit. (Or write two talks and do both, I guess.) They're pretty different – the summit is a more informal thing (no video, smaller room), mostly just core devs, more of a working meeting kind of thing where you can argue about technical details. |
Thanks, I may do that then – if a core dev invite me to do so – I wouldn't have dared otherwise. I'm not even sure you can suggest a language summit proposal yet. For the normal talk proposal here is what I have so far: https://gist.github.com/Carreau/20881c6c70f1cde9878db7aa247d432a |
Slides and demo (videos) during PyCon2019 Language Summit: https://github.com/Carreau/talks/tree/master/2019-05-01-Language-Summit One question was how to handle non-asyncio in Core Python, REPL. My response was to not take care of that in the first time, but provide the building blocks for alternative REPL, in a second time provide an async-input, and a way to register runner for alternative async libraries. |
Yeah, I think this is pretty simple: the runtime/stdlib should provide the primitives to compile top-level async code, get coroutines, etc., and then a REPL like ipython can take care of handing that off to asyncio or whatever library they want. Maybe in the long run the builtin REPL should get async support "out of the box", but that's much less clear, and anyway we should split that off into a separate issue if we want to discuss it. async-input isn't even useful for ipython, is it? you use prompt-toolkit :-) |
Exactly. FWIW I'm +1 to have this in 3.8. Do you have a patch for this? If not I can take a look at this myself tomorrow or the day after. |
You don't have to use prompt_toolkit (https://github.com/ipython/rlipython), but yes we don't need this.
No, I do not have a patch. I can provide a few test case and I am happy to spend some task to sit-down and discuss what we exactly do so far in IPython. I'm flying back Sunday morning. |
That would be helpful!
Yes, let's do that around Friday/Saturday (feel free to ping me via a Twitter DM). I'm also leaving on Sunday. |
Extra notes from in-person discussion; One of the other question was wether Also for info all the top level async-await PR and issues on IPython can be found here: https://github.com/ipython/ipython/issues?q=label%3Aasync%2Fawait+is%3Aclosed |
I recall the idea of passing a specific flag to Than compile can return a code object with CO_COROUTINE flag set. Returned code object can be analyzed for this flag and executed with Actual coroutine executor can be asyncio/trio/twisted/whatever, it depends on what code calls this Did I miss something? |
No I think for the async stuff that should be a big improvement already. I'l love for something like 'exec' but where not only we can have multiple statement, but where the last statement behave like single and "expression statements that evaluate to something other than None will be printed". The other thing would be for this mode to not turn the the fist statement into a module docstring in the AST if it is a string. I know that most of these are slightly orthogonal but do have backward compatibility consequences. I'll try to be at PyCon "Mentored Sprints" this afternoon, I'll be ha[[y to be mentored into contributing this to CPython. I'm also happy to discuss writing this in a pep. |
Sorry, I don't know all the compilation workflow details to help you quickly (and will be very busy on other tasks during the sprint). Yuri will be absent on sprints. |
Here's a VERY rough first implementation to play with: 1st1@ad2ed0a |
Thank Yuri for the guidance; I worked on it, cleaned things up a bit and posted a draft PR (bpo-13148) with some example. That helps cleaning up a lot of code; and in the PR is a ~30 line example that implement an asyncio-repl. |
Matthias, please use #57357 for pointing on github pull requests. |
I see the 3.8 feature freeze seem to be end of next-week; do you think that async-exec (gh-13148) has a chance of getting in ? I'm happy to do modification to the PR but would need some more reviews. I'm happy to take some other tasks of your plate is that allow this to squeeze in before feature freeze. Thanks. |
I'll be working on CPython on Friday. Will take a look at your PR first thing. |
Thanks, let me know if the is anything I can do for you in exchange; also thanks again for sitting with me and stepping me through the things at PyCon. |
Great! |
Would it be possible to document this change in What's New in Python 3.8? |
Yes, Elvis and I will take care of that later. |
Any idea why PR 13148 has been linked to unrelated bugs.python.org issues? I saw 3 of them: bpo-35363, bpo-25234, bpo-33725. https://mail.python.org/pipermail/python-dev/2019-May/157592.html |
Well, it would be nice to get a first mention before the next release, to see all new shiny Python 3.8 features ;-) The text can be reworded later if needed ;-) |
Could it be due to rebasing and force-pushing ? Cause I did force-push on this branch a couple of times... |
And I'm guessing you will collect what's in NEWS.d ? Otherwise I'm happy to contribute some text. let me know the best way. |
Maybe you used "git merge" and your PR "contained" changes from other issues? |
Would be great if you could make a PR to add an entry to whatsnew/3.8.rst (as Victor suggests) |
One option to document it is to add a new "builtins" section to document the new flag inside "Improved Modules" category: |
I quasi-nerver merge, either
Ok, i'll do this. |
Done in #13484 |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: