Python 为什么需要重新引发asyncio.CancelleError?
我有以下Python 为什么需要重新引发asyncio.CancelleError?,python,exception,websocket,python-asyncio,aiohttp,Python,Exception,Websocket,Python Asyncio,Aiohttp,我有以下aiohttpWebSocket处理程序: 异步def websocket_处理程序(请求): ws=None 如果request.app中没有“我的websocket客户端”: request.app['my-websocket-clients']=[] 打印('Websocket连接开始',request.path,request.query) 尝试: ws=aiohttp.web.WebSocketResponse(自动分页=True,心跳=10.0,压缩=True) 等待ws.p
aiohttp
WebSocket处理程序:
异步def websocket_处理程序(请求):
ws=None
如果request.app中没有“我的websocket客户端”:
request.app['my-websocket-clients']=[]
打印('Websocket连接开始',request.path,request.query)
尝试:
ws=aiohttp.web.WebSocketResponse(自动分页=True,心跳=10.0,压缩=True)
等待ws.prepare(请求)
request.app['my-websocket-clients'].append(ws)
打印('Websocket连接就绪',len(request.app['my-Websocket-clients']))
ws中消息的异步:
等待websocket_消息(请求、ws、msg)
除asyncio.exceptions.CancelledError外,错误为e:
打印('Websocket连接关闭不干净'+str(e))
#~~~~~~~你在这里长大~~~~~~
除:
traceback.print_exc()
最后:
尝试:
等待ws.close()
除:
traceback.print_exc()
如果在request.app['my-websocket-clients'中有ws:
request.app['my-websocket-clients'].remove(ws)
打印('Websocket连接已关闭',len(request.app['my-Websocket-clients']))
如果ws为无:
ws=aiohttp.web.Response()
返回ws
根据“在几乎所有情况下,必须重新引发异常[asyncio.exceptions.CancelleError]
是否需要在代码中标记的位置重新引发异常?这将需要我重写将客户机从客户机列表中删除的代码。我是否还需要重新提升除asyncio.exceptions.CancelledError
块之后的块之外的catch all块
如果在这种情况下需要重新引发asyncio.exceptions.CancelledError
,为什么首先需要重新引发?在哪些情况下,我不需要重新引发该异常?在捕获取消错误的情况下,您需要非常小心
在Python 3.8之前,很容易用以下代码无意中抑制此错误:
试试看:
等待操作()
除例外情况外:
log.error('操作失败。将稍后重试')
由于Python 3.8CanceledError
是BaseException
的子类,因此必须始终显式处理此错误:
试试看:
等待操作()
除取消错误外:
#清理
提升
除例外情况外:
log.error('操作失败。将稍后重试')
这里的主要问题是,无法取消抑制取消错误的任务
但是,无论如何,重新提出的建议不是绝对的,而是针对一般情况提出的。如果您知道自己在做什么,您可以处理取消错误
并完成协同程序,而无需再次抛出它。应该注意的是,当一个任务被取消时,它的取消通常看起来像一个cancelederror
s链,它将从最内部的wait
调用抛出,并抛出wait
s链,在这种情况下,我们打破了这个链,必须正确处理这种情况
在aiohttp
websocket处理程序的情况下,如果您确保正确清理资源并且处理程序退出,我认为不重新引发cancelederror
是可以接受的。因此,由于我正在等待websocket\u消息(request,ws,msg)
,此方法也可以等待其他方法(就像对数据库的写入/读取),重新提升它以便它可以传播到数据库“驱动程序”中是有意义的?实际上,如果你说它是从最里面的wait
调用抛出的,那么我理解的情况正好相反。重新引发异常是有意义的,因为没有理由像我那样返回空的aiohttp.web.Response()
,而是让aiohttp
处理它。