Describe your issue here.
x in one of the [ ])x in each of the [ ])Filling out the following details about bugs will help us solve your issue sooner.
slackclient version: 2.5.0
python version: 3.7.6 (venv)
asyncio.get_event_loop() in order to use the same as the projectweb_client and use it to send a message backThe message is sent
RuntimeError: this event loop is already running.
What is actually happening is that the loop set to the RTMClient is not being shared with the attached WebClient.
The following code does the trick, but it's a workaround and not a real solution
import os
from slack import RTMClient
import asyncio
loop = asyncio.get_event_loop()
@RTMClient.run_on(event="message")
def say_hello(**payload):
data = payload['data']
web_client = payload['web_client']
#### WORKAROUND #########################
# Manually set the project's loop on the WebClient, even when it was set on the parent RTMClient
web_client._event_loop = loop
# Maybe you will also need the following line uncommented
# web_client.run_async = True
##########################################
if 'Hello' in data['text']:
channel_id = data['channel']
thread_ts = data['ts']
user = data['user']
web_client.chat_postMessage(
channel=channel_id,
text=f"Hi <@{user}>!",
thread_ts=thread_ts
)
slack_token = os.environ["SLACK_API_TOKEN"]
rtm_client = RTMClient(token=slack_token, loop=loop)
rtm_client.start()
If the main project's loop is not the common one but an uvloop, you will need to make some mods before getting the loop in order to set it on the RTMClient
...
import asyncio
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
...
FYI: this commit contains a test case reproducing this issue and it shows two possible solutions for it even with slackclient 2.5.0. https://github.com/seratch/python-slackclient/commit/6fb428723a67e1e3b22da27c4378f3c9b18291d3
In the forthcoming release, the library will address the issue for run_async=False mode (the default). The solution I'm currently thinking as the best is implementing the internals of the WebClient never relies on asyncio's event loop if run_async is False.
The internal modification won't bring any breaking changes to the library users. WebClient just ignores the event loop in the case. So, with future versions, you no longer need to have the necessity to share an event loop as long as you go with the default run_async=False option.
On the other hand, for the run_async=True option, the solution is as easy as checking if a loop was set on the RTMClient. If so, add it to the params when creating the WebClient (action the RTMClient does internally).
If you manually create a WebClient, you can set your own loop (as you can do on RTMClient creation)
I've updated the demo code to highlight the workaround I've made and need to be solved by doing the proper loop/run_async params passing from RTMClient to WebClient
Let me close this issue now as #662 resolved this for the run_async=False mode.
馃憢 slackclient 2.6.0rc1 is out. The pre-release version contains fixes for your issue described here.
https://pypi.org/project/slackclient/2.6.0rc1/
One week later from now, we'll be releasing version 2.6.0 to PyPI.
If you have a chance, could you try the release candidate version out and let us know your feedback? Thank you very much for being patient with this issue.
Most helpful comment
FYI: this commit contains a test case reproducing this issue and it shows two possible solutions for it even with slackclient 2.5.0. https://github.com/seratch/python-slackclient/commit/6fb428723a67e1e3b22da27c4378f3c9b18291d3
In the forthcoming release, the library will address the issue for
run_async=Falsemode (the default). The solution I'm currently thinking as the best is implementing the internals of the WebClient never relies on asyncio's event loop ifrun_asyncis False.The internal modification won't bring any breaking changes to the library users.
WebClientjust ignores the event loop in the case. So, with future versions, you no longer need to have the necessity to share an event loop as long as you go with the defaultrun_async=Falseoption.