为什么此示例代码中需要run_forever?

时间:2019-07-23 07:59:45

标签: python-3.x websocket python-asyncio

在python asyncio websockets库中,该示例调用run_forever()。为什么要这样做?

run_until_complete()是否应该阻止并运行websockets循环?

#!/usr/bin/env python

# WS server example

import asyncio
import websockets

async def hello(websocket, path):
    name = await websocket.recv()
    print(f"< {name}")

    greeting = f"Hello {name}!"

    await websocket.send(greeting)
    print(f"> {greeting}")

start_server = websockets.serve(hello, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
# if you comment out the above line, this doesn't work, i.e., the server
# doesn't actually block waiting for data...

如果我注释掉run_forever(),程序将立即结束。

start_server是库等待返回的。为什么run_until_complete不足以使其在hello()上被阻止/等待?

1 个答案:

答案 0 :(得分:0)

websockets.serve只需启动服务器并立即退出。 (它仍然需要等待,因为配置服务器可能需要网络通信。)因此,您需要实际运行事件循环。

由于服务器被设计为无限期运行,因此无法通过将协程传递给run_until_complete来以通常的方式运行事件循环。由于服务器已经启动,因此没有协程可以运行,您只需要让事件循环运行并完成其工作即可。这是run_forever有用的地方-它告诉事件循环无限期地运行(执行先前计划的任务,例如属于服务器的任务),或者直到调用loop.stop使其停止为止

在Python 3.7和更高版本中,应该使用asyncio.run运行asyncio代码,这将创建一个新的事件循环,因此上述技巧将不起作用。在现代异步代码中完成上述操作的一个好方法是使用serve_forever方法(未经测试):

async def my_server():
    ws_server = await websockets.serve(hello, "localhost", 8765)
    await ws_server.server.serve_forever()

asyncio.run(my_server())