python - 在 asyncio.wait 中捕获异常
问题描述
我有一个应用程序通过 websocket 连接从 Python 服务器获取消息。如果客户端在两者之间断开连接,服务器将无法发送消息。我想利用这一点并在发生这种情况时引发异常,以便正确清理而不会出现很多错误。
async def status(websocket, message):
try:
print("\nDEBUG: "+message)
await asyncio.wait([websocket.send(message)])
except:
raise Abort()
当客户端断开连接时,此函数会引发错误。
DEBUG: Waiting for sale to start
Task exception was never retrieved
future: <Task finished name='Task-79' coro=<WebSocketCommonProtocol.send() done, defined at C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\site-packages\websockets\protocol.py:521> exception=ConnectionClosedError('code = 1006 (connection closed abnormally [internal]), no reason')>
Traceback (most recent call last):
File "C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\site-packages\websockets\protocol.py", line 827, in transfer_data
message = await self.read_message()
File "C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\site-packages\websockets\protocol.py", line 895, in read_message
frame = await self.read_data_frame(max_size=self.max_size)
File "C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\site-packages\websockets\protocol.py", line 971, in read_data_frame
frame = await self.read_frame(max_size)
File "C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\site-packages\websockets\protocol.py", line 1047, in read_frame
frame = await Frame.read(
File "C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\site-packages\websockets\framing.py", line 105, in read
data = await reader(2)
File "C:\Users\321vi\AppData\Local\Programs\Python\Python38\lib\asyncio\streams.py", line 721, in readexactly
raise exceptions.IncompleteReadError(incomplete, n)
asyncio.exceptions.IncompleteReadError: 0 bytes read on a total of 2 expected bytes
现在,我知道这是由于文档asyncio
中提到的异常处理不当造成的,但我无法编写适当的方法来处理异常。我确实尝试复制此答案并使其正常工作。但是它根本不发送任何消息。令人惊讶的是,根本没有错误消息。这是我复制粘贴后的代码handler
async def status(websocket, message):
print("\nDEBUG: "+message)
done, pending = await asyncio.wait([websocket.send(message)])
assert not pending
future, = done
if future.exception() is websockets.ConnectionClosedError:
raise Abort()
我也尝试剥离asyncio.wait()
并使用简单websocket.send()
,但这不适用于这个应用程序。我对 Python 没有经验,Future
因此将不胜感激。从技术上讲,我可能heartbeats
每次都可以用来检查连接是否有效,但这可能会消耗更多的网络,所以我不想这样做。
解决方案
如果您只在等待一个协程,请直接执行,异常会自然传播:
try
print("\nDEBUG: "+message)
await websocket.send(message)
except Exception:
raise Abort()
没有理由使用asyncio.wait
旨在等待多个任务的。将它用于一个协程会产生大量开销:一个新任务被创建、调度、运行并最终在一个元素集中返回,并且必须在单独的步骤中检查其结果。这基本上就是最后一个代码片段所做的。
没有 的简单websocket.send(message)
(当用 定义时async def
)await
实际上什么都不做。从技术上讲,它从协程函数创建一个 couroutine 对象,但该 couroutine 没有被执行。
推荐阅读
- laravel - Laravel 如何新建 Contract 类文件和 Service 类文件
- spring - 在 Spring Boot REST Open API 3 中保持相同的 URL 但合同更改?
- jquery - 如何在调度程序 dhtmlx 中为 Longleave、Fullday、HalfDay 创建不同的颜色?
- android - 如何将徽章从 firebase-admin 发送到 android 应用程序?
- node.js - SynataxError:编译 ejs 文件时出现意外的标识符
- python - gnupg 加密文件失败 ENCRYPTION_COMPLIANCE_MODE
- javascript - Squarespace - 有没有办法可以改变这个预加载的背景颜色?
- angular - 在@SqsListener 中设置 maxNumberOfMessages
- prometheus - 在 Prometheus 和 Grafana 中建模每小时收到的总请求数
- arrays - 连接列表中的修复字符串并添加到 JSON 数组中的问题