notebook: Can't invoke asyncio event_loop after tornado 5.0 update
On fresh python3.6 venv, after pip install jupyter && jupyter notebook
and starting a new python3.6 notebook:
import asyncio
async def foo():
return 42
asyncio.get_event_loop().run_until_complete(foo())
throws:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-5-3ad9bf216544> in <module>()
----> 1 asyncio.get_event_loop().run_until_complete(foo())
/usr/local/lib/python3.6/asyncio/base_events.py in run_until_complete(self, future)
452 future.add_done_callback(_run_until_complete_cb)
453 try:
--> 454 self.run_forever()
455 except:
456 if new_task and future.done() and not future.cancelled():
/usr/local/lib/python3.6/asyncio/base_events.py in run_forever(self)
406 self._check_closed()
407 if self.is_running():
--> 408 raise RuntimeError('This event loop is already running')
409 if events._get_running_loop() is not None:
410 raise RuntimeError(
RuntimeError: This event loop is already running
If I specify tornado==4.5.3
before pip install jupyter
, it works fine
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 41
- Comments: 73 (32 by maintainers)
Links to this issue
Commits related to this issue
- Enforce tornado 4.x until the Tornado 5.0 support is fixed Tornado 5.x starts it's own event loop, breaking other packages: https://github.com/jupyter/notebook/issues/3397 http://www.tornadoweb.org/e... — committed to vdboor/python-zeep by vdboor 6 years ago
- Enforce tornado 4.x until the Tornado 5.0 support is fixed Tornado 5.x starts it's own event loop, breaking other packages: https://github.com/jupyter/notebook/issues/3397 http://www.tornadoweb.org/e... — committed to vdboor/python-zeep by vdboor 6 years ago
- Enforce tornado 4.x until the Tornado 5.0 support is fixed Tornado 5.x starts it's own event loop, breaking other packages: https://github.com/jupyter/notebook/issues/3397 http://www.tornadoweb.org/e... — committed to vdboor/python-zeep by vdboor 6 years ago
- Enforce tornado 4.x until the Tornado 5.0 support is fixed Tornado 5.x starts it's own event loop, breaking other packages: https://github.com/jupyter/notebook/issues/3397 http://www.tornadoweb.org/e... — committed to vdboor/python-zeep by vdboor 6 years ago
- request: Use a separate worker thread for synchoronous APIs * Running another event loop in the same thread or scheduling coroutines from synchronous codes are NOT allowed. * Since Jupyter now use... — committed to lablup/backend.ai-client-py by achimnol 6 years ago
- Fix issue related to oauth2 - https://github.com/jupyter/notebook/issues/3397 — committed to eugene-s/docker-celery-flower by eugene-s 6 years ago
- Pin tornado version too See https://github.com/jupyter/notebook/issues/3397 — committed to broadinstitute/regevlab-jupyter-docker by deleted user 5 years ago
@parmentelat pip3 install tornado==4.5.3 solved the issue
but wait, as far as I am concerned this means I can’t run anything tainted with asyncio in a notebook
which will asymptotically amount to saying, I can’t run anything in a notebook 😉
it that right, or am I missing something obvious ?
For those interested, I’ve just a created package called nest_asyncio that solves the problem by patching asyncio to allow nested event loops. To use it in a notebook is a matter of putting
somewhere near the top.
I have the same issue…the only way I was able to make it work was:
heart = broken
to make min’s suggestion more concrete, I could work around this issue by just issuing
edit:
I expect the jupyter server needs to be restarted as wellIt is working correctly with python3.7, Tornado 5.1 and ipykernel 4.8.2 on ArchLinux by manually updating python-ipykernel to the last version (not working with python-ipykernel-4.6.1)
i see this issue as closed. but seems the only solution to this is to pin versions of notebook and tornado. is that really the only solution?
We should have prereleases of IPython 7 and ipykernel 5 next week that will enable top-level async/await in IPython or a notebook.
Because ipykernel itself relies on asyncio, if we want to achieve the ability for users to call
get_event_loop().run_until_complete()
, we have just a few options:Personally, I view the fact that asyncio and tornado are running to be a feature, as user code can launch long-running coroutines on the main eventloop and they will keep running in the background. This would be challenging if the loop were in a thread.
So my inclination is for now, recommend
nest_asyncio
at the user-level and finish shipping ipykernel 5 / ipython 7 with top-level await / mainloop. We could even add a special exception handler for this RuntimeError to point folks at nest_asyncio or autoawait:And then revisit the possibility of putting the main eventloop into a background thread at a future date.
At the risk of stating the obvious, I’d just like to outline the following discrepency between what I get in a terminal - be it python or ipython - and in a notebook
I am not sure that I quite understand the other discussion there ipython/ipython#10390 but regardless, it is my feeling that something is wrong at this very early point already.
Running
notebook=6.0.0
does not solve the problem in our case (gremlinpython
).Downgrading
notebook
does:Yep, that’s expected. The kernel itself runs on an event loop, and as of Tornado 5.0, it’s using the asyncio event loop. So the asyncio event loop is always running in the kernel. As far as I know, we haven’t figured out a way to deal with this yet.
Thank you @satra. I understand and completely agree. It’s a very complex stack happening here, coupled with extremely varied technical levels. I have no intention of expecting folks to change how issues are reported. I just believe that redirection should happen as early in the analysis as possible and, over time, users will understand. That said, users are always welcome to start that process here (and rightly so).
@azag0 Exactly. Having the asyncio loop on the main thread always running basically breaks most asyncio-based apps/libraries out there. Any new comer to the asyncio world that tries to run the code of some asyncio tutorial on Jupyter will be incredibly frustrated as most sample code they find on the web (which usually uses
loop.run_until_complete
orloop.run_forever
) just simply won’t run.@Carreau I am not familiar with the internals of ipykernel, but is it possible to have the ipykernel/tornado asyncio loop running in a background thread instead of the main thread?
The new Jupyterhub has:
after which I am unable to install the older version of tornado in the main environment of the Jupyterhub.
Does this mean that until this issue is solved, the root/main environment of any Jupyterhub>=0.9.2 (at least) is broken?
We are aware of the issue and working on making it easier to run async code within a notebook, without having to manipulate the event loop yourself.
Getting it to work was already challenging, having it function on multiple python version is far from being easy, and we lack people willing to test our in-progress pull request to give feedback. In particular on the IPython side:
And ipykernel side:
There a a lot of extremely subtle behavior,
Any help to do other tasks unrelated to this bug might give us some band with to focus on this, but it’s relatively complex code that requires multiple hours of focused time, which is becoming rare.
I agree with @satra, this issue seems like it should be open, not closed. The Python REPL and the IPython REPL work fine, jupyter notebook does not.
The problem still occurs with notebook 6.1.3.
@kevin-bates - we were able to update our notebooks with the
nest_asyncio
solution and that works now on binderYou can also use
await foo()
, if you go back to software releases from within the last two years!On Thu, Nov 14, 2019, 01:41 PointCloudNiphon notifications@github.com wrote:
@lmeyerov Have you tried:
I agree on that point. For instance, with Aiohttp, rather then the blocking
web.run_app(app)
, one can doIdeally, all asyncio Python packages should allow such use. Unfortunately, one cannot turn a package that doesn’t provide such functionality into a package that does easily. Even better, packages would provide an async context manager:
If this was common, the current situation with the Ipython kernel wouldn’t really be such an issue.
Quick update on conda:
While conda won’t allow downgrading to
tornado==4.5.3
on Python 3.7:I have confirmed overriding
tornado
throughpip
does work:I am not sure if this will cause some minor bugs elsewhere or if the conda dependency check is just being overly strict though.
Most asyncio packages have an entry point that deals with the loop. Asyncio itself has
asyncio.run()
which won’t work in the Ipython kernel at the moment. Aiohttp hasweb.run_app()
. Other packages have other functions. These functions set up the loop, run the coroutines, and do application-specific nontrivial teardowns of the loop. Currently, one would have to go one step lower, and reimplement these methods in the Notebook. This is not feasible.@Carreau Those integrations look really nice, but will they be strictly optional? In other words, will there be a way to have the asyncio loop NOT running at all on Jupyter Notebook going forward?
I use Jupyter as a scratchpad for development and as a developer of asyncio-based apps, not being able to run
loop.run_forever
orloop.run_until_complete
(or the newasyncio.run
in 3.7) from Jupyter pretty much makes it useless as a scratchpad for me. I am sticking to Python 3.6.6 with tornado 4.5.3 for now, but that clearly isn’t sustainable… (conda won’t let me install Python 3.7 with tornado 4.5.3)@getzze
Running the code snippet in the first post of this thread with Python 3.7.0, Tornado 5.1 and ipykernel 4.8.2 still gives me the same “RuntimeError: This event loop is already running”.
Using the new asyncio.run method instead of run_until_complete gives a slightly different “RuntimeError: asyncio.run() cannot be called from a running event loop”.
The real problem is imho not with jupyter or tornado, but with this decision for asyncio.
I’d like to second this request for an update
As far as I am concerned, this is a major hindrance, as anything remotely useful tends to have some dosage of asyncio these days
Hey all, just wondering if there is there any update on this issue?
I’d be inclined to figure out a way to run the user’s coroutines on the existing event loop rather than starting a new thread. Threads cause all sorts of problems.
Probably related to the fact that
“On Python 3,
IOLoop
is always a wrapper around theasyncio
event loop.”as listed in “Backwards-compatibility notes” of tornado 5.0: http://www.tornadoweb.org/en/stable/releases/v5.0.0.html#backwards-compatibility-notes