为什么使用 asyncio 服务器作为上下文管理器 * 和 * 调用 serve_forever()



asyncio streams 的 Python 3.7 文档包含一个 TCP echo 服务器示例:

import asyncio
async def handle_echo(reader, writer):
    data = await reader.read(100)
    message = data.decode()
    addr = writer.get_extra_info('peername')
    print(f"Received {message!r} from {addr!r}")
    print(f"Send: {message!r}")
    writer.write(data)
    await writer.drain()
    print("Close the connection")
    writer.close()
async def main():
    server = await asyncio.start_server(
        handle_echo, '127.0.0.1', 8888)
    addr = server.sockets[0].getsockname()
    print(f'Serving on {addr}')
    async with server:
        await server.serve_forever()
asyncio.run(main())

这是我特别感兴趣的片段:

async with server:
    await server.serve_forever()

因此,我们正在做两件事:

  • 我们将asyncio.Server用作上下文管理器,对于该上下文管理器,(从该页面("保证 Server 对象已关闭,并且在 async with 语句完成时不接受新连接"。
  • 我们打电话给Server.serve_forever().这通常会开始侦听(如果尚未启动(,并确保在取消协程时关闭服务器。当我们到达这些行时,我们已经调用了start_server(默认start_serving=True(,因此唯一的效果是确保服务器关闭。

似乎这些基本上在做同样的事情。为什么示例中包含这两行?最合理的实际应用是否可能同时包含两者?

答案是不必要的冗余可以在这里看到。如果服务器已接受连接,则可以调用 serve_forever 方法。

Server对象方法说明中,serve_forever协程示例如下所示:

async def client_connected(reader, writer):
    # Communicate with the client with
    # reader/writer streams.  For example:
    await reader.readline()
async def main(host, port):
    srv = await asyncio.start_server(
        client_connected, host, port)
    await srv.serve_forever()
asyncio.run(main('127.0.0.1', 0))

更多信息可以在官方文档中找到。

最新更新