title: How do I run Python asyncio code in a Jupyter notebook?
body: <p>I have some asyncio code which runs fine in the Python interpreter (CPython 3.6.2). I would now like to run this inside a Jupyter notebook with an IPython kernel.</p>
  
  <p>I can run it with</p>
  
  <pre><code>import asyncio
  asyncio.get_event_loop().run_forever()
  </code></pre>
  
  <p>and while that seems to work it also seems to block the notebook and doesn't seem to play nice with the notebook.</p>
  
  <p>My understanding is that Jupyter uses Tornado under the hood so I tried to <a href="http://www.tornadoweb.org/en/stable/asyncio.html" rel="noreferrer">install a Tornado event loop as recommended in the Tornado docs</a>: </p>
  
  <pre><code>from tornado.platform.asyncio import AsyncIOMainLoop
  AsyncIOMainLoop().install()
  </code></pre>
  
  <p>However that gives the following error:</p>
  
  <pre><code>---------------------------------------------------------------------------
  AssertionError                            Traceback (most recent call last)
  &lt;ipython-input-1-1139449343fc&gt; in &lt;module&gt;()
        1 from tornado.platform.asyncio import AsyncIOMainLoop
  ----&gt; 2 AsyncIOMainLoop().install()
  
  ~\AppData\Local\Continuum\Anaconda3\envs\numismatic\lib\site- packages\tornado\ioloop.py in install(self)
      179         `IOLoop` (e.g.,     :class:`tornado.httpclient.AsyncHTTPClient`).
      180         """
  --&gt; 181         assert not IOLoop.initialized()
      182         IOLoop._instance = self
      183 
  
  AssertionError: 
  </code></pre>
  
  <p>Finally I found the following page: <a href="http://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Asynchronous.html" rel="noreferrer">http://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Asynchronous.html</a></p>
  
  <p>so I added a cell with the following code:</p>
  
  <pre><code>import asyncio
  from ipykernel.eventloops import register_integration
  
  @register_integration('asyncio')
  def loop_asyncio(kernel):
      '''Start a kernel with asyncio event loop support.'''
      loop = asyncio.get_event_loop()
  
      def kernel_handler():
          loop.call_soon(kernel.do_one_iteration)
          loop.call_later(kernel._poll_interval, kernel_handler)
  
      loop.call_soon(kernel_handler)
      try:
          if not loop.is_running():
              loop.run_forever()
      finally:
          loop.run_until_complete(loop.shutdown_asyncgens())
          loop.close()
  </code></pre>
  
  <p>and in the next cell I ran:</p>
  
  <pre><code>%gui asyncio
  </code></pre>
  
  <p>That worked but I don't really understand why and how it works. Can someone please explain that to me?</p>