下面是一个简单的回显服务器。但是,如果客户端在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
没有task complete
,timer cancelled
和writer closed
。
更新
找出问题,看起来任务实际上已取消,但是异常被忽略,通过捕获CancelledError
解决了问题
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
完成代码。不再需要超时代码。检查以下接受的solution:
async def new_session(reader, writer):
print("new session started")
try:
await asyncio.wait_for(process(reader, writer), timeout=5)
except asyncio.TimeoutError as te:
print(f'time is up!{te}')
finally:
writer.close()
print("writer closed")
参考方案
有没有更好的方法来实现超时?
您可以使用 asyncio.wait_for
代替timeout
。它具有类似的语义,但是已经带有asyncio。另外,您可以等待将来返回以检测是否发生了超时。
我试图弄清楚如何检查Wikipedia文章是否存在。例如,https://en.wikipedia.org/wiki/Food 存在,但是https://en.wikipedia.org/wiki/Fod 不会,页面只是说:“维基百科没有此名称的文章。”谢谢! 参考方案 >>> import urllib >>> prin…
Python uuid4,如何限制唯一字符的长度 - python在Python中,我正在使用uuid4()方法创建唯一的字符集。但是我找不到将其限制为10或8个字符的方法。有什么办法吗?uuid4()ffc69c1b-9d87-4c19-8dac-c09ca857e3fc谢谢。 参考方案 尝试:x = uuid4() str(x)[:8] 输出:"ffc69c1b" Is there a way to…
Python-如何检查Redis服务器是否可用 - python我正在开发用于访问Redis Server的Python服务(类)。我想知道如何检查Redis Server是否正在运行。而且如果某种原因我无法连接到它。这是我的代码的一部分import redis rs = redis.Redis("localhost") print rs 它打印以下内容<redis.client.Redis o…
Python-crontab模块 - python我正在尝试在Linux OS(CentOS 7)上使用Python-crontab模块我的配置文件如下:{ "ossConfigurationData": { "work1": [ { "cronInterval": "0 0 0 1 1 ?", "attribute&…
python asyncio run_forever或True - python我应该在代码中替换while True(不使用asyncio)还是应该使用asyncio事件循环来实现相同的结果。目前,我正在处理某种与“ zeromq”连接的“工作者”,接收一些数据,然后对外部工具(服务器)执行一些请求(http)。一切都以普通的阻塞IO编写。使用asyncio事件循环摆脱while True: ...是否有意义?将来可能会用asynci…