Python中一行代码捕获多个异常的方法

Python中一行代码捕获多个异常的方法

技术背景

在Python编程中,异常处理是一种重要的机制,用于处理程序运行过程中可能出现的错误。有时候,我们需要在一个except块中捕获多个不同类型的异常,以执行相同的处理逻辑。了解如何在一行代码中捕获多个异常,可以让代码更加简洁和高效。

实现步骤

Python 3及以后版本

在Python 3中,可以使用括号将多个异常类型括起来,形成一个元组,然后使用as关键字将捕获到的异常实例赋值给一个变量。示例代码如下:

1
2
3
4
try:
may_raise_specific_errors()
except (SpecificErrorOne, SpecificErrorTwo) as error:
handle(error)

Python 2版本

在Python 2中,除了可以使用和Python 3类似的语法外,还可以使用逗号将异常类型和变量名分隔开,但这种语法在Python 2.6和2.7中已被弃用,在Python 3中不再支持。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Python 2.6及以后建议使用的语法
try:
mainstuff()
except (KeyboardInterrupt, EOFError) as err:
print(err)
print(err.args)
sys.exit(0)

# Python 2.5及以前的语法(已弃用)
try:
mainstuff()
except (KeyboardInterrupt, EOFError), err:
print err
print err.args
sys.exit(0)

使用suppress上下文管理器(Python 3.4及以后)

如果只是想忽略某些异常,可以使用contextlib模块中的suppress上下文管理器。示例代码如下:

1
2
3
4
from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
do_something()

预定义异常元组

如果需要频繁使用大量的异常类型,可以预定义一个异常元组,避免多次重复输入。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
ConnectErrs = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
# Do a connection and return some data
return(received_data)

def some_function(var_a, var_b, ...):
try:
o = connect(url, data)
except ConnectErrs as e:
# Do the recovery stuff
# Do normal stuff you would do if an exception does not occur

Python 3.11及以后的except*语法

从Python 3.11开始,可以使用except*语法来处理多个异常。ExceptionGroup对应一组一起传播的异常,可以使用except*语法来处理。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
try:
raise ExceptionGroup('Example ExceptionGroup', (
TypeError('Example TypeError'),
ValueError('Example ValueError'),
KeyError('Example KeyError'),
AttributeError('Example AttributeError')
))
except* TypeError:
...
except* ValueError as e:
...
except* (KeyError, AttributeError) as e:
...

核心代码

Python 3捕获多个异常

1
2
3
4
5
try:
# 可能会抛出异常的代码
result = 1 / 0
except (ZeroDivisionError, TypeError) as e:
print(f"捕获到异常: {e}")

使用suppress上下文管理器

1
2
3
4
from contextlib import suppress

with suppress(ZeroDivisionError, TypeError):
result = 1 / 0

Python 3.11的except*语法

1
2
3
4
5
6
7
8
9
try:
raise ExceptionGroup('Example Group', (
ZeroDivisionError('Division by zero'),
TypeError('Wrong type')
))
except* ZeroDivisionError as eg:
print(f"捕获到ZeroDivisionError异常组: {eg}")
except* TypeError as eg:
print(f"捕获到TypeError异常组: {eg}")

最佳实践

  • 明确指定异常类型:为了避免隐藏潜在的错误,建议明确指定要捕获的异常类型,而不是捕获所有异常。
  • 使用预定义元组:如果需要频繁使用大量的异常类型,可以预定义一个异常元组,提高代码的可读性和可维护性。
  • 避免使用已弃用的语法:在Python 2.6及以后的版本中,应避免使用逗号分隔异常类型和变量名的语法,使用as关键字替代。

常见问题

逗号分隔异常类型和变量名的语法在Python 3中不支持

在Python 3中,使用逗号分隔异常类型和变量名的语法会导致语法错误。应使用as关键字来赋值异常实例。

括号是必需的

在捕获多个异常时,括号是必需的,因为早期的语法使用逗号来将错误对象赋值给一个名称。

异常对象的作用域

在Python 3中,异常对象在except块结束后会超出作用域。


Python中一行代码捕获多个异常的方法
https://119291.xyz/posts/2025-05-09.python-catching-multiple-exceptions-in-one-line/
作者
ww
发布于
2025年5月9日
许可协议