Документация Python 3.7 для асинхронных потоков включает пример эхо-сервера TCP :
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закрыто и не принимает новые соединения после завершения асинхронного оператора с оператором ". - Мы звоним
Server.serve_forever()
.Обычно начинается прослушивание (если оно еще не запущено) и обеспечивается закрытие сервера при отмене сопрограммы.К тому времени, когда мы достигаем этих строк, мы уже назвали start_server
(со значением по умолчанию start_serving=True
), поэтому единственный эффект - обеспечение закрытия сервера.
Кажется,как они делают по существу то же самое.Почему обе строки включены в пример?Могут ли наиболее разумные практические применения включать оба?