我一直在尝试在Slack中制作一个机器人,即使它还没有完成处理先前的命令,它仍然保持响应,所以它可以去做一些需要一些时间而不会锁定的东西。它应该返回先完成的任何东西。
我想我已经在那里得到了一部分:它现在不会忽略在早期命令运行之前键入的内容。但它仍然不允许线程超过"彼此 - 一个名为first的命令将首先返回,即使它需要更长的时间才能完成。
import asyncio
from slackclient import SlackClient
import time, datetime as dt
token = "my token"
sc = SlackClient(token)
@asyncio.coroutine
def sayHello(waitPeriod = 5):
yield from asyncio.sleep(waitPeriod)
msg = 'Hello! I waited {} seconds.'.format(waitPeriod)
return msg
@asyncio.coroutine
def listen():
yield from asyncio.sleep(1)
x = sc.rtm_connect()
info = sc.rtm_read()
if len(info) == 1:
if r'/hello' in info[0]['text']:
print(info)
try:
waitPeriod = int(info[0]['text'][6:])
except:
print('Can not read a time period. Using 5 seconds.')
waitPeriod = 5
msg = yield from sayHello(waitPeriod = waitPeriod)
print(msg)
chan = info[0]['channel']
sc.rtm_send_message(chan, msg)
asyncio.async(listen())
def main():
print('here we go')
loop = asyncio.get_event_loop()
asyncio.async(listen())
loop.run_forever()
if __name__ == '__main__':
main()
当我在Slack聊天窗口中输入/hello 12
和/hello 2
时,僵尸程序现在会响应这两个命令。但是,在完成/hello 2
命令之前,它不会处理/hello 12
命令。我对asyncio的理解是一项正在进行的工作,所以我很可能犯了一个非常基本的错误。我在previous question中被告知像sc.rtm_read()
这样的东西是阻塞函数。这是我问题的根源吗?
非常感谢, 亚历
答案 0 :(得分:1)
正在发生的事情是您的listen()
协程在yield from sayHello()
声明处阻止。只有sayHello()
完成后listen()
才能继续快乐。{1}}关键是yield from
语句(或Python 3.5+中的await
)是阻塞的。它将两个协同程序链接在一起,并且“父”协程无法完成,直到链接的“子”协程完成。 (但是,不属于同一链接链的'邻近'协程可以在此期间自由进行。)
在这种情况下,释放sayHello()
而不阻止listen()
的简单方法是使用listen()
作为专用侦听协程,并将所有后续操作卸载到自己的Task
中而不是包装器,因此不会阻碍listen()
响应后续传入的消息。这些方面的东西。
@asyncio.coroutine
def sayHello(waitPeriod, sc, chan):
yield from asyncio.sleep(waitPeriod)
msg = 'Hello! I waited {} seconds.'.format(waitPeriod)
print(msg)
sc.rtm_send_message(chan, msg)
@asyncio.coroutine
def listen():
# connect once only if possible:
x = sc.rtm_connect()
# use a While True block instead of repeatedly calling a new Task at the end
while True:
yield from asyncio.sleep(0) # use 0 unless you need to wait a full second?
#x = sc.rtm_connect() # probably not necessary to reconnect each loop?
info = sc.rtm_read()
if len(info) == 1:
if r'/hello' in info[0]['text']:
print(info)
try:
waitPeriod = int(info[0]['text'][6:])
except:
print('Can not read a time period. Using 5 seconds.')
waitPeriod = 5
chan = info[0]['channel']
asyncio.async(sayHello(waitPeriod, sc, chan))