2

I am facing a known problem of running asyncio-aware functions in Jupyter (https://github.com/jupyterlab/jupyterlab/issues/4399, https://github.com/ipython/ipython/issues/11030 and the reference in https://blog.jupyter.org/ipython-7-0-async-repl-a35ce050f7f7).

I just update the Slack Python library to version 2.0 and I am facing the same issue as above, namely

import slack

client = slack.WebClient(token=os.environ["SLACK_TOKEN"])
client.chat_postMessage(channel="@flavien", text="test")

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-12-20f89b3af945> in <module>
      2 
      3 client = slack.WebClient(token=os.environ["SLACK_TOKEN"])
----> 4 asyncio.run(client.chat_postMessage(channel="@flavien", text="test"))

~/miniconda3/envs/analytics/lib/python3.6/site-packages/slack/web/client.py in chat_postMessage(self, channel, **kwargs)
    289         """
    290         kwargs.update({"channel": channel})
--> 291         return self.api_call("chat.postMessage", json=kwargs)
    292 
    293     def chat_unfurl(

~/miniconda3/envs/analytics/lib/python3.6/site-packages/slack/web/base_client.py in api_call(self, api_method, http_verb, files, data, params, json)
    133             return future
    134 
--> 135         return self._event_loop.run_until_complete(future)
    136 
    137     def _validate_xoxp_token(self):

~/miniconda3/envs/analytics/lib/python3.6/site-packages/nest_asyncio.py in run_until_complete(self, future)
     61             return f.result()
     62         else:
---> 63             return self._run_until_complete_orig(future)
     64 
     65     bogus_handle = asyncio.Handle(None, None, loop)

~/miniconda3/envs/analytics/lib/python3.6/asyncio/base_events.py in run_until_complete(self, future)
    453         future.add_done_callback(_run_until_complete_cb)
    454         try:
--> 455             self.run_forever()
    456         except:
    457             if new_task and future.done() and not future.cancelled():

~/miniconda3/envs/analytics/lib/python3.6/asyncio/base_events.py in run_forever(self)
    410         if events._get_running_loop() is not None:
    411             raise RuntimeError(
--> 412                 'Cannot run the event loop while another loop is running')
    413         self._set_coroutine_wrapper(self._debug)
    414         self._thread_id = threading.get_ident()

RuntimeError: Cannot run the event loop while another loop is running

Despite a lot of trials, I could not manage to make the thing run. Is there any way to circumvent this issue?

My packages versions with Python 3.6.6

jupyter                   1.0.0                      py_2    conda-forge
ipykernel                 5.1.0         py36h24bf2e0_1002    conda-forge
tornado                   6.0.2            py36h516909a_0    conda-forge
slackclient               2.0.1                    pypi_0    pypi

Thanks in advance for your help.

Flavien Lambert
  • 690
  • 1
  • 9
  • 22
  • https://stackoverflow.com/questions/47518874/how-do-i-run-python-asyncio-code-in-a-jupyter-notebook – QHarr May 10 '19 at 05:52
  • Hi @QHarr, thanks for your reply. I do not understand though. If I get it correctly, one needs to get the existing loop instead of trying to start a new one. But I can't do that since the start is managed by the `slack` module, right? I thought that it was exactly the point about nested loops. – Flavien Lambert May 10 '19 at 08:48

2 Answers2

0

The problem according to me is that you are running the piece of code inside your jupyter cell or ipython. Try running it as a stand-alone python code and let me know if you see the same error.

The reason you see this error is that jupyter already runs a loop for your cell that drives the kernel, internally.

Sagar Kar
  • 177
  • 1
  • 2
  • 10
0

One workaround you could try is to run the relevant code in a separate process:

import slack
from multiprocessing import Process

def main():
    client = slack.WebClient(token=os.environ["SLACK_TOKEN"])
    client.chat_postMessage(channel="@flavien", text="test")

p = Process(target=main, args=())
p.start()
p.join()

However, from my testing, if the underlying code uses loop = asyncio.get_event_loop() the retrieved loop will be the one running on Jupyter (which may cause some unwanted behaviour).

The problem is avoided if the underlying code uses asyncio.run(coro()) or uses a new loop with loop = asyncio.new_event_loop().

Jean Monet
  • 2,075
  • 15
  • 25