Python中手动抛出异常的方法

Python中手动抛出异常的方法

技术背景

在Python编程中,异常处理是保证程序健壮性的重要手段。当程序遇到不符合预期的情况时,需要手动抛出异常,以便调用者能够捕获并处理这些异常。

实现步骤

抛出特定异常

使用最符合语义的异常构造函数抛出异常,使异常信息更具体。

1
raise ValueError('A very specific bad thing happened.')

避免抛出通用异常

避免使用通用的 Exception ,因为捕获它会捕获所有子类异常,可能会隐藏潜在的错误。

1
2
3
4
5
6
7
8
9
10
11
12
# 不建议的做法
raise Exception('I know Python!')

# 示例代码
def demo_bad_catch():
try:
raise ValueError('Represents a hidden bug, do not catch this')
raise Exception('This is the exception you expect to handle')
except Exception as error:
print('Caught this error: ' + repr(error))

demo_bad_catch()

最佳实践:raise 语句

使用最具体的异常构造函数,并可传递任意数量的参数。

1
2
3
4
5
6
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')

try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)

最佳实践:except 子句

except 子句中,使用无参数的 raise 语句重新抛出异常,以保留堆栈跟踪信息。

1
2
3
4
5
6
7
8
9
import logging

logger = logging.getLogger(__name__)

try:
do_something_in_app_that_breaks_easily()
except AppError as error:
logger.error(error)
raise

Python 3中的异常链

在Python 3中,可以使用 from 关键字实现异常链,保留堆栈跟踪信息。

1
raise RuntimeError('specific message') from error

创建自定义异常

如果需要表示应用程序中特定的错误情况,可以创建自定义异常类。

1
2
3
4
5
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''

if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')

核心代码

抛出异常示例

1
2
3
4
5
6
7
8
9
10
11
# 抛出带参数的异常
try:
raise ValueError("I have raised an Exception")
except ValueError as exp:
print("Error", exp)

# 抛出无参数的异常
try:
raise ValueError
except ValueError as exp:
print("Error", exp)

重新抛出异常示例

1
2
3
4
5
6
7
8
9
10
11
12
13
def somefunction():
print("some cleaning")

a = 10
b = 0
result = None

try:
result = a / b
print(result)
except Exception:
somefunction()
raise

异常链示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyCustomException(Exception):
pass

a = 10
b = 0
result = None
try:
try:
result = a / b
except ZeroDivisionError as exp:
print("ZeroDivisionError -- ", exp)
raise MyCustomException("Zero Division ") from exp
except MyCustomException as exp:
print("MyException", exp)
print(exp.__cause__)

最佳实践

  • 使用最具体的异常类,使异常信息更具可读性和可维护性。
  • except 子句中使用无参数的 raise 语句重新抛出异常,保留堆栈跟踪信息。
  • 创建自定义异常类,以便在应用程序中表示特定的错误情况。

常见问题

抛出通用异常的问题

抛出通用的 Exception 可能会隐藏潜在的错误,并且无法被特定的异常处理程序捕获。

手动操作堆栈跟踪的问题

手动操作堆栈跟踪(如使用 sys.exc_info())容易出错,并且在Python 2和Python 3之间存在兼容性问题。建议使用无参数的 raise 语句重新抛出异常。

已弃用的方法

  • raise ValueError, 'message' 在Python 3中已弃用。
  • raise 'message' 在现代Python版本中会引发 TypeError,因为它不是 BaseException 类型。

Python中手动抛出异常的方法
https://119291.xyz/posts/2025-05-09.python-manually-raise-exception/
作者
ww
发布于
2025年5月9日
许可协议