Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在异步IO服务器中实现超时?_Python_Python 3.x_Python Asyncio_Session Timeout - Fatal编程技术网

Python 如何在异步IO服务器中实现超时?

Python 如何在异步IO服务器中实现超时?,python,python-3.x,python-asyncio,session-timeout,Python,Python 3.x,Python Asyncio,Session Timeout,下面是一个简单的echo服务器。但是如果客户端在10秒钟内没有发送任何内容,我想关闭连接 import asyncio async def process(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): print("awaiting for data") line = await reader.readline() print(f"received {line}") writer.wr

下面是一个简单的echo服务器。但是如果客户端在10秒钟内没有发送任何内容,我想关闭连接

import asyncio


async def process(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
    print("awaiting for data")
    line = await reader.readline()
    print(f"received {line}")
    writer.write(line)
    print(f"sent {line}")
    await writer.drain()
    print(f"Drained")


async def timeout(task: asyncio.Task, duration):
    print("timeout started")
    await asyncio.sleep(duration)
    print("client unresponsive, cancelling")
    task.cancel()
    print("task cancelled")


async def new_session(reader, writer):
    print("new session started")
    task = asyncio.create_task(process(reader, writer))
    timer = asyncio.create_task(timeout(task, 10))
    await task
    print("task complete")
    timer.cancel()
    print("timer cancelled")
    writer.close()
    print("writer closed")


async def a_main():
    server = await asyncio.start_server(new_session, port=8088)
    await server.serve_forever()


if __name__ == '__main__':
    asyncio.run(a_main())
如果客户端发送一条消息,它工作正常。但另一种情况是,当客户端处于静默状态时,它不工作

当客户端发送消息时:

new session started
awaiting for data
timeout started
received b'slkdfjsdlkfj\r\n'
sent b'slkdfjsdlkfj\r\n'
Drained
task complete
timer cancelled
writer closed
当客户端在打开连接后处于静默状态时

new session started
awaiting for data
timeout started
client unresponsive, cancelling
task cancelled
没有
任务完成
计时器取消
写入程序关闭

  • 上面的代码有什么问题
  • 有没有更好的方法来实现超时

  • 更新

    解决了问题,看起来任务实际上被取消了,但异常被默默忽略,通过捕获
    cancelederror

    async def new_session(reader, writer):
        print("new session started")
        task = asyncio.create_task(process(reader, writer))
        timer = asyncio.create_task(timeout(task, 10))
        try:
            await task
        except asyncio.CancelledError:
            print(f"Task took too long and was cancelled by timer")
        print("task complete")
        timer.cancel()
        print("timer cancelled")
        writer.close()
        print("writer closed")
    
    第二部分仍然存在。有没有更好的方法来实现超时


    更新2

    使用
    等待
    完成代码。不再需要超时代码。接受以下支票:


    我在建立连接时使用以下代码。我建议您的代码使用wait_for

    fut = asyncio.open_connection( self.host, self.port, loop=self.loop )
    try:
       r, w = await asyncio.wait_for(fut, timeout=self.connection_timeout)
    except asyncio.TimeoutError:
       pass
    
    有没有更好的方法来实现超时


    您可以使用而不是
    超时
    。它具有类似的语义,但已经附带了asyncio。此外,您还可以等待它返回的未来,以检测是否发生超时。

    您可以使用
    asyncio。请等待
    而不是
    timeout
    @user4815162342谢谢。是否要将其添加为答案?我会接受。
    open\u连接
    是指当您是客户时。问题是服务器。这是一个如何使用wait_的例子,wait_是pythonic解决方案,用于您想要做的事情。我不知道它可以用于任何可等待的事情。向上投票。
    fut = asyncio.open_connection( self.host, self.port, loop=self.loop )
    try:
       r, w = await asyncio.wait_for(fut, timeout=self.connection_timeout)
    except asyncio.TimeoutError:
       pass