簡體   English   中英

與Slack bot的Python asyncio

[英]Python asyncio with Slack bot

我正在嘗試使用asyncio制作一個簡單的Slack機器人,主要使用此處的示例用於asyncio部分, 此處用於Slack機器人部分。

這兩個例子都是自己工作的,但是當我把它們放在一起時,似乎我的循環沒有循環:它經過一次然后死掉。 如果info是一個長度等於1的列表,當在其中包含機器人的聊天室中鍵入消息時,會發生協程,但它永遠不會被觸發。 (所有協同程序現在都在嘗試打印消息,如果消息包含“/ time”,它會讓機器人在其詢問的聊天室中打印時間)。 鍵盤中斷也不起作用,我每次都要關閉命令提示符。

這是我的代碼:

import asyncio
from slackclient import SlackClient
import time, datetime as dt

token = "MY TOKEN"
sc = SlackClient(token)

@asyncio.coroutine
def read_text(info):
    if 'text' in info[0]:
        print(info[0]['text'])
        if r'/time' in info[0]['text']:
            print(info)
            resp = 'The time is ' + dt.datetime.strftime(dt.datetime.now(),'%H:%M:%S')
            print(resp)
            chan = info[0]['channel']
            sc.rtm_send_message(chan, resp)


loop = asyncio.get_event_loop()
try:
    sc.rtm_connect()
    info = sc.rtm_read()
    if len(info) == 1:
        asyncio.async(read_text(info))
    loop.run_forever()

except KeyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

我認為這是循環部分被打破,因為它似乎永遠不會到達協程。 所以也許一個更簡單的問這個問題的方法是什么是我的try:語句阻止它像我在后面的asyncio示例中循環? sc.rtm_connect()有什么不喜歡的嗎?

我是asyncio的新手,所以我可能做了一些愚蠢的事情。 這是嘗試和解決這個問題的最好方法嗎? 最終我希望機器人做一些需要花費很長時間才能完成計算的東西,並且我希望它在那個時候保持響應,所以我認為我需要使用asyncio或某種程度的線程,但我願意更好的建議。

非常感謝,Alex

我將其更改為以下內容並且有效:

import asyncio
from slackclient import SlackClient
import time, datetime as dt

token = "MY TOKEN"    
sc = SlackClient(token)

@asyncio.coroutine
def listen():
    yield from asyncio.sleep(1)
    x = sc.rtm_connect()
    info = sc.rtm_read()
    if len(info) == 1:
        if 'text' in info[0]:
            print(info[0]['text'])
            if r'/time' in info[0]['text']:
                print(info)
                resp = 'The time is ' + dt.datetime.strftime(dt.datetime.now(),'%H:%M:%S')
                print(resp)
                chan = info[0]['channel']
                sc.rtm_send_message(chan, resp)

    asyncio.async(listen())


loop = asyncio.get_event_loop()
try:
    asyncio.async(listen())
    loop.run_forever()

except KeyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

不完全確定為什么要修復它,但我改變的關鍵事情是將sc.rtm_connect()調用放在協程中並使其成為x = sc.rtm_connect() 我也在最后調用了listen()函數,這似乎是讓它永遠循環的原因,因為如果我把它拿出來,機器人不響應。 我不知道這是不是應該設置這種東西的方式,但它似乎在處理早期命令時繼續接受命令,我的松弛聊天看起來像這樣:

me [12:21 AM] 
/time

[12:21] 
/time

[12:21] 
/time

[12:21] 
/time

testbotBOT [12:21 AM] 
The time is 00:21:11

[12:21] 
The time is 00:21:14

[12:21] 
The time is 00:21:16

[12:21] 
The time is 00:21:19

請注意,它不會錯過任何我/time請求,如果它不是異步執行此操作,它會發生這種情況。 此外,如果有人試圖復制這個,你會注意到如果你鍵入“/”,松弛會打開內置命令菜單。 我通過在前面鍵入一個空格來解決這個問題。

感謝您的幫助,如果您知道更好的方法,請告訴我。 它似乎不是一個非常優雅的解決方案,並且我使用cntrl-c鍵盤中斷結束后無法重啟機器人 - 它說

Task exception was never retrieved
future: <Task finished coro=<listen() done, defined at asynctest3.py:8> exception=AttributeError("'NoneType' object has no attribute 'recv'",)>
Traceback (most recent call last):
  File "C:\Users\Dell-F5\AppData\Local\Programs\Python\Python35-32\Lib\asyncio\tasks.py", line 239, in _step
    result = coro.send(None)
  File "asynctest3.py", line 13, in listen
    info = sc.rtm_read()
  File "C:\Users\Dell-F5\Envs\sbot\lib\site-packages\slackclient\_client.py", line 39, in rtm_read
    json_data = self.server.websocket_safe_read()
  File "C:\Users\Dell-F5\Envs\sbot\lib\site-packages\slackclient\_server.py", line 110, in websocket_safe_read
    data += "{0}\n".format(self.websocket.recv())
AttributeError: 'NoneType' object has no attribute 'recv'

我猜這意味着它沒有很好地關閉websockets。 無論如何,這只是一個煩惱,至少主要問題是固定的。

亞歷克斯

在協程內部進行阻塞IO調用會破壞使用asyncio的目的(例如, info = sc.rtm_read() )。 如果您沒有選擇,請使用loop.run_in_executor在其他線程中運行阻塞調用。 但是要小心,可能需要一些額外的鎖定。

但是,似乎有一些基於asyncio的松弛客戶端庫可以使用:


編輯: Butterfield使用Slack實時消息傳遞API。 它甚至提供了一個echo bot示例 ,看起來非常像您要實現的目標:

import asyncio
from butterfield import Bot

@asyncio.coroutine
def echo(bot, message):
    yield from bot.post(
        message['channel'],
        message['text']
    )

bot = Bot('slack-bot-key')
bot.listen(echo)
butterfield.run(bot)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM