[WIP] async repl continuation#11155
Conversation
For example trio runner is `run(function, args...)` the signature `run(function, arg)` can easily be transformed to `run(function(args))` but not vice versa.
otherwise pass the real callable
blocking run_cell is a wrapper around run_cell_async The async path is always taken, and blocking only occurs at the top-level run_cell, rather than at the lowest-level exec. This is the only way I can see to allow execution of async code when the outer application (ipykernel) is already running an eventloop.
|
Thanks for reviving that.
|
No, my bad, just seem to be random. |
I don't think this is true, unfortunately. Maybe 3.8 if someone steps up to do it; I suspect the main asyncio maintainers will be too busy to get to it. @minrk obviously tornado is the natural place to start given how ipykernel works, but have you thought at all about how to support alternative event loops? |
Well, ok, maybe 3.8, but in nightly at least
That is also my concern, but then I guess we have 2 questions: |
|
I've pushed a tiny fix to the With this running IPython under trio does seem to work, with the asyncio loop not running. Not sure what that does in a notebook though. |
|
Ok, one of the error left is in nesting IPython, as the event loop is already running: DetailsThat, I'm also not sure how to fix. |
|
So one possibility is to run the nested instances using different event loop; or to drop the support for nested embed (for now?) until all is async and we can run an async embed. |
|
If I understood correctly, from the work @Carreau did with the loop_runners, this should work with any runner as long as that runner can run Now, what happens in a case like ipykernel where tornado (and therefore also asyncio) is already running, I'm not sure how to deal with that. Right now, ipython/ipykernel#323 unconditionally uses i.e. run_cell_async could do something like: if loop_running:
return coro() # will be awaited outside
else:
return loop_runner(coro())@Carreau re: nested IPythons, I'm really not sure how to solve that one. I made this a blocking wrapper around a fundamentally async core because it was the only way to get it to work without duplicating all of the methods as async and non-async variants all the way down. asyncio explicitly doesn't do nested eventloops, so too allow nested IPythons with blocking calls, we would have to make sure that we never instantiate an eventloop. Similarly, to allow nested IPythons with async, we would need to allow embedding IPython in a running eventloop, which should be quite doable (ipykernel is already doing this by simply calling Or we can try to violate the "no nested eventloops" assumption of asyncio by handling our own stack of clearing/replacing the current loop. |
|
I'm happy to drop the necessity to have nested IPython's but we should likely ask on the mailing list first for how many users of this feature we have. I think the need for
I don't believe in (2) we need a lot of async integrations so I'm happy to clear/replace eventloop. @njsmith how hard would it be to have a version of @contextmanager
def new_context():
import trio._core._run as tcr
old_runner = getattr(tcr.GLOBAL_RUN_CONTEXT, 'runner', None)
old_task = getattr(tcr.GLOBAL_RUN_CONTEXT, 'task', None)
if old_runner:
del tcr.GLOBAL_RUN_CONTEXT.runner
if old_task:
del tcr.GLOBAL_RUN_CONTEXT.task
yield
if old_runner:
tcr.GLOBAL_RUN_CONTEXT.runner = old_runner
if old_task:
tcr.GLOBAL_RUN_CONTEXT.task = old_task |
|
AFAICT this commit make multiple nested embedded IPython's works (using trio, and above context manager, and relying on trio's internal). You can (of course) make IPython crash if you try to switch to asyncio loop in one of the nested embedded ones. |
|
cc @mrocklin, would that be of any use when interacting with dask interactively ? See ipython/ipykernel#323 as well when running that inside a notebook. |
|
There is a significant amount of difference with master now and rebase is tough. In order to keep some history I'm going to close and open a PR where all the work as been merged into a single commit and the merge commits from this removed. |
|
see #11265 |

This continues #10390 with the following additions:
run_cell_asyncmethod that is itself a coroutine,for enabling async execution when the eventloop is already running.
This is currently implemented by wrapping
run_cell_asyncinloop_runner()to provide therun_cellblocking API. At this point, this has one major drawback: when the eventloop is already running, run_cell will now always fail, rather than when async execution is requested. I don't quite have a solution for this yet, but I'll try to think of one.Related PR supporting async execution in ipykernel incoming, which should be a demonstrator for asyncio by default when running with tornado 5.
cc @Carreau @njsmith
closes #11030