我开始使用websockets和asyncio
,并且很难理解背后的逻辑。我过去在Python上使用过线程以及在Javascript上使用AJAX调用(因此我对多线程的概念(I / O绑定)有所了解,并且调用过程会对结果进行异步操作)。
示例服务器如下。我的目标是提供一个websocket连接和两个函数,每10秒钟调用一次,无需等待结果(无论函数处理多长时间,每10秒钟只调用一次)。
import time
import arrow
import websockets
import asyncio
async def time1(websocket):
# simulation of a time intensive operation
time.sleep(2)
msg = '1 ' + arrow.now()
print(msg)
websocket.send(msg)
async def time2(websocket):
# simulation of a time intensive operation
time.sleep(3)
msg = '2 ' + arrow.now()
print(msg)
websocket.send(msg)
async def update_info(websocket, path):
while True:
now = arrow.now()
if not now.second % 10:
time1(websocket)
if not now.second % 10:
time2(websocket)
time.sleep(1)
start_server = websockets.serve(update_info, 'localhost', 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
我预计,一旦客户端连接,在接下来的整整10秒内,功能就会被触发。它们会在2秒和3秒后完成,然后在接下来的整整10秒钟内开火等等。
我得到的是
D:/Dropbox/dev/domotique/webserver.py:708: RuntimeWarning: coroutine 'time1' was never awaited
time1(websocket)
D:/Dropbox/dev/domotique/webserver.py:710: RuntimeWarning: coroutine 'time2' was never awaited
time2(websocket)
并且没有任何消息被发送或打印。
为什么我必须await
为协同程序?我想以update_info
形式触发它们并忘记它们(=让它们处理它们并让它们通过websocket发送数据)。 我的方法出了什么问题?
答案 0 :(得分:5)
await
有效地将等待的协程耦合到事件循环,等待它完成,然后继续。如果你没有await
协程,那么这不会发生。
如果您只想在后台运行协程(更像是Task
),请使用asyncio.ensure_future(my_coroutine())
,这将剥离Task
并让您继续其他项目。
await
语句,否则事件循环将会遇到该任务,除非它返回。事件循环给人的印象是一次做两件事就是在不同的代码之间来回徘徊。 await
语句是事件循环可以进行杂乱的点。因此,当一段代码正在等待时,另一段代码将继续运行。一旦其他代码点击了await
,那么该阵容中的下一段代码就会获得批准等等。换句话说,请注意放置awaits
的位置,并设计你的代码,使长时间运行的代码不会阻止从异步中受益的更动态的组件。