面试题答案
一键面试异步编程中错误报告原则的调整分析
- 异常传播方式:
- 在同步编程中,异常会立即在发生的位置传播,调用栈清晰,易于定位问题。例如函数
func1
调用func2
,func2
抛出异常,异常会直接沿着调用栈向上传播到func1
调用func2
的位置。 - 而异步编程中,
async
函数返回的是一个coroutine
对象,当coroutine
内部抛出异常时,并不会立即传播。只有当coroutine
被await
时,异常才会传播到await
的位置。这就需要开发者清楚await
的位置与异常实际发生位置的关系,避免异常处理不及时或处理位置不当。
- 在同步编程中,异常会立即在发生的位置传播,调用栈清晰,易于定位问题。例如函数
- 并发任务中的异常处理:
- 在同步编程中,多个任务顺序执行,一个任务出错会停止后续任务执行。而异步编程使用
asyncio.gather
等方法并发执行多个coroutine
时,如果其中一个coroutine
抛出异常,默认情况下其他coroutine
会继续执行。这就要求开发者手动处理每个coroutine
的异常,否则异常可能被忽略。
- 在同步编程中,多个任务顺序执行,一个任务出错会停止后续任务执行。而异步编程使用
代码示例及处理方法
import asyncio
async def async_task():
# 模拟一个可能出错的异步任务
raise ValueError("这是一个异步任务中的错误")
async def main():
tasks = [async_task()]
try:
await asyncio.gather(*tasks)
except ValueError as e:
print(f"捕获到异常: {e}")
if __name__ == "__main__":
asyncio.run(main())
在上述代码中:
- 异常产生:
async_task
函数中抛出了一个ValueError
异常。 - 异常处理:在
main
函数中,使用asyncio.gather
并发执行async_task
。通过try - except
块捕获async_task
中抛出的异常。如果没有这个try - except
块,async_task
中的异常会导致程序终止,但不会被捕获处理,可能让开发者难以发现问题。这样通过在await asyncio.gather
的位置捕获异常,就实现了对异步任务中异常的合理处理。