<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Thanks for bringing this up -- I think it will be good to get to the bottom of this, before the Jupyter folks accidentally get everyone to use an approach that is unsound. Maybe they can be redirected to a better strategy, or maybe they can convince us to change asyncio: it's totally possible that the reasoning behind this restriction is no longer really valid.<br></div><div><br></div><div>I expect that Yury will have to jump in, but I believe he's busy with a release. I also hope Nathaniel has something to say -- I wonder if trio supports nested event loops? (And maybe a Tornado developer?)</div></div><div><br></div><div>In the meantime, my take on this is that a nested event loop invocation by a nominally synchronous function, i.e. something that calls run_until_complete(), violates a guarantee that asyncio makes: callbacks may only run when `await` is called, and thus any state that is shared between callbacks or tasks is implicitly protected from mutation *between* `await` calls. This means that asyncio programmers don't have to worry about a class of nasty threading bugs caused by arbitrary interleaving of threads. For example, take these three lines from asyncio/queue.py:</div><div><br></div><div> self._put(item)<br> self._unfinished_tasks += 1<br> self._finished.clear()<br></div><div><br></div><div>Because there's no `await` visible here, as a reader I know that the accounting of finished and unfinished tasks here will always be in a consistent state when some other piece of code receives control.</div><div><br></div><div>Also, I looked into nest_asyncio, and I definitely think it should not be recommended -- it disables use of the asyncio accelerator classes implemented in C (starting with Python 3.6).</div><div><br></div><div>One final thing. What we're talking about here is nested invocation of the "event pump". There's another form of nested event loop invocation where two separate event loop objects exist. That is a much more worrisome scenario, because callbacks associated with one event loop won't run at all while one is waiting for a task on the other loop. Fortunately that's not what is requested here. :-)<br></div><div dir="ltr"><div><br></div>--Guido<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 22, 2019 at 10:00 AM Daniel Nugent <<a href="mailto:nugend@gmail.com" target="_blank">nugend@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div name="messageBodySection">Hello, I was hoping that the Async SIG might have some suggestions on how to deal with this sort of issue:<br>
<br>
More frameworks are adopting asyncio as time marches on. A notable example of this is Jupyter and the Python kernels it supports (please see announcement here: <a href="https://blog.jupyter.org/ipython-7-0-async-repl-a35ce050f7f7" target="_blank">blog.jupyter.org/ipython-7-0-async-repl-a35ce050f7f7</a>). This was enabled by a change in Tornado version 5.0 to support the asyncio event loop.<br>
<br>
The problem is that this makes any code which inadvertently ran an asyncio event loop (that is, calls through a blocking API provided by a library implemented in asyncio) fail. The Jupyter developers seem to feel that this is a deficiency in the asyncio event loop model and suggest all users encountering such a problem adopt the patch module nest_asyncio (<a href="https://github.com/jupyter/notebook/issues/3397#issuecomment-419474214" target="_blank">github.com/jupyter/notebook/issues/3397#issuecomment-419474214</a>).<br>
<br>
However, it is my understanding that the Python team strongly feels this is not the correct path: <a href="https://bugs.python.org/issue33523" target="_blank">bugs.python.org/issue33523</a><a href="https://bugs.python.org/issue29558" target="_blank">bugs.python.org/issue29558</a><a href="https://bugs.python.org/issue22239" target="_blank">bugs.python.org/issue22239</a><br>
<br>
I have been trying to figure out the right way to work around this issue such that a library implemented with asyncio that provides a synchronous API will not cause a problem and have come up short thus far. I was considering investigating the janus sync/async queue as a way of facilitating communication between the different modes, but I am not sure that the scenario I describe reflects the intended usage. That is, an outer asyncio driven program fragment calls into middle synchronous code, which calls to inner asynchronous code. It seems that janus is mostly intended to facilitate communication between a single outer asynchronous layer and an inner synchronous layer. However, the documentation is a little sparse so I may just not understand it yet.<br>
<br>
I don't believe I'm the only person struggling to figure out how to deal with this sort of situation, so I think this would be useful for the community to figure out a solid answer to. For example, I found this blog post which outlines the same sort of problem and suggests that they elected to use nest_asyncio <a href="http://threespeedlogic.com/python-tworoutines.html" target="_blank">threespeedlogic.com/python-tworoutines.html</a><br>
<br>
If anyone could provide guidance on how to go forward, I would appreciate it.<br>
<br>
I would also like to understand the decision making around not allowing event loop nesting/reentrancy as seen in the <a href="http://bugs.python.org" target="_blank">bugs.python.org</a>issues I referenced so that I may explain the tradeoffs of possibly adopting the nest_asyncio patch module (for the sake of argument, lets ignore the possible issues with non-standard event loops) better to my peers.<br>
<br>
Thank you,<br>
<br>
-Dan Nugent</div>
</div>
_______________________________________________<br>
Async-sig mailing list<br>
<a href="mailto:Async-sig@python.org" target="_blank">Async-sig@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/async-sig" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/async-sig</a><br>
Code of Conduct: <a href="https://www.python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">https://www.python.org/psf/codeofconduct/</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="m_-8078389646824457606gmail-m_2270951311967886545gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div></div></div></div>