编程后端开发人员

描述Python中异常处理的机制。try/except/finally块是如何工作的,raise的作用是什么,常见的陷阱有哪些?

用 Hintsage AI 助手通过面试

答案

在Python中,异常处理通过try/except/else/finally结构和raise语句来实现。

try定义了受保护的代码块。如果其中发生异常,控制权将转移到最近的适当except块。如果没有异常发生,则执行else块(如果存在)。finally块始终执行—无论是否有异常(例如,用于释放资源)。

raise语句显式引发异常或重新引发当前异常(在except块中未指定类型)。

示例:

try: x = 1 / 0 except ZeroDivisionError as e: print(f"错误: {e}") else: print("没有错误") finally: print("始终执行")

输出:

错误: division by zero
始终执行

细节:

  • 在嵌套处理程序中,except的顺序很重要:从特定类型到更通用的(否则特定的将不会被处理)。
  • finally块不能阻止异常的重新抛出(如果在finally中插入raise— 仅最新的"错误"有效)。

误导性问题

问题: "如果在try块和finally中引发不同的异常,会发生什么?"

答案: 来自finally的异常会"覆盖"来自try的异常:外部会抛出在finally中引发的异常。

def foo(): try: raise ValueError("在try中") finally: raise IndexError("在finally中") try: foo() except Exception as e: print(repr(e)) # 输出: IndexError('在finally中')

由于对主题细节缺乏了解而导致的实际错误示例


故事

在ETL过程中,在finally中无条件地关闭与数据库的连接,但忘记了在finally中可能会引发异常(例如,如果连接已经关闭)。结果是,来自finally的"隐藏"异常完全吞噬了来自主代码的异常,调试变得异常复杂。


故事

使用多个except链:从一般的except Exception到特定的。结果是,所有特定的except都被"封杀"— 低级别的异常没有单独捕获,导致特定错误的处理变得困难。


故事

在web服务中,在except块中忘记通过"raise"抛出异常,记录错误,但允许继续执行。结果是实际错误被"丢失",程序继续在不正确的状态下运行。