Python的异常处理
1. Syntax Errors (语法错误)
语法错误,也称为解析错误,可能是您在学习 Python 时遇到的最常见的抱怨:
>>> while True print('Hello world') File "<stdin>", line 1 while True print('Hello world') ^ SyntaxError: invalid syntax
解析器重复有问题的行并显示一个小“箭头”,指向检测到错误的行中最早的点。错误是由箭头前面的标记引起的(或至少在箭头处检测到):在示例中,在函数处检测到错误,因为在它之前缺少print()冒号 ( )。':' 打印文件名和行号,以便您知道在输入来自脚本的情况下在哪里查看。
2. Exceptions
即使语句或表达式在语法上是正确的,当尝试执行它时也可能会导致错误。在执行过程中检测到的错误称为异常并且不是无条件致命的:您很快就会学习如何在 Python 程序中处理它们。然而,大多数异常不是由程序处理的,并且会导致如下所示的错误消息:
>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero >>> 4 + spam*3 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate str (not "int") to str
错误消息的最后一行表明发生了什么。异常有不同的类型,类型作为消息的一部分打印:示例中的类型是ZeroDivisionError,NameError和TypeError. 打印为异常类型的字符串是发生的内置异常的名称。这对于所有内置异常都是正确的,但对于用户定义的异常不必是正确的(尽管它是一个有用的约定)。标准异常名称是内置标识符(不是保留关键字)。
该行的其余部分根据异常类型及其原因提供详细信息。
错误消息的前面部分以堆栈回溯的形式显示了发生异常的上下文。一般来说,它包含一个堆栈回溯,列出源代码行;但是,它不会显示从标准输入读取的行。
内置异常列出了内置异常及其含义。
3. 处理异常
可以编写处理选定异常的程序。看下面的例子,它要求用户输入,直到输入一个有效的整数,但允许用户中断程序(使用或操作系统支持的任何东西);请注意,通过引发异常来表示用户生成的中断。Control-CKeyboardInterrupt
>>> while True: ... try: ... x = int(input("Please enter a number: ")) ... break ... except ValueError: ... print("Oops! That was no valid number. Try again...") ...
该try
语句的工作方式如下。
首先,执行try
子句(thetry
和 except
关键字之间的语句)。
如果没有发生异常,则跳过 except
子句try
并完成语句的执行。
如果在执行子句期间发生异常try
,则跳过子句的其余部分。except
然后,如果它的类型与以关键字命名的异常匹配 ,则执行except
子句,然后在 try/except
块之后继续执行。
如果发生与except
子句中指定的异常不匹配的异常,则将其传递给外部try语句;如果没有找到处理程序,则它是一个未处理的异常,并且执行停止并显示如上所示的消息。
一条try
语句可能有多个except
子句,用于指定不同异常的处理程序。最多执行一个处理程序。处理程序仅处理发生在相应try
子句中的异常,而不处理同一try
语句的其他处理程序中发生的异常。except
子句可以将 多个异常命名为带括号的元组,例如:
... except (RuntimeError, TypeError, NameError): ... pass
except
如果子句中的类是同一个类或其基类,则子句中的类与异常兼容(但反之则不然——列出派生类的 except
子句与基类不兼容)。例如,以下代码将按该顺序打印 B、C、D:
class B(Exception): pass class C(B): pass class D(C): pass for cls in [B, C, D]: try: raise cls() except D: print("D") except C: print("C") except B: print("B")
请注意,如果将except
子句反转(使用first),它将打印 B, B, B — 第一个匹配的except
子句被触发。except B
所有异常都继承自BaseException
,因此可以用作通配符。使用时要格外小心,因为用这种方式很容易掩盖真正的编程错误!它还可以用于打印错误消息,然后重新引发异常(允许调用者也处理异常):
import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except OSError as err: print("OS error: {0}".format(err)) except ValueError: print("Could not convert data to an integer.") except BaseException as err: print(f"Unexpected {err=}, {type(err)=}") raise
或者,最后一个 except 子句可以省略异常名称,但是必须从 检索异常值sys.exc_info()[1]
。
try...except
语句有一个可选的else
子句,当它出现时,它必须跟在所有except
子句之后。如果try
子句不引发异常,则它对于必须执行的代码很有用。例如:
for arg in sys.argv[1:]: try: f = open(arg, 'r') except OSError: print('cannot open', arg) else: print(arg, 'has', len(f.readlines()), 'lines') f.close()
使用该else子句比在该子句中添加额外的代码要好,try因为它可以避免意外捕获不是由受try... except语句保护的代码引发的异常。
当异常发生时,它可能有一个关联的值,也称为异常的参数。参数的存在和类型取决于异常类型。
except
子句可以在异常名称之后指定一个变量。该变量绑定到一个异常实例,其参数存储在 instance.args.
为方便起见,定义了异常实例, __str__()
因此可以直接打印参数而无需引用.args.
也可以在引发异常之前先实例化异常,然后根据需要向其添加任何属性。
>>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print(type(inst)) # the exception instance ... print(inst.args) # arguments stored in .args ... print(inst) # __str__ allows args to be printed directly, ... # but may be overridden in exception subclasses ... x, y = inst.args # unpack args ... print('x =', x) ... print('y =', y) ... <class 'Exception'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs
如果异常有参数,它们将作为未处理异常的消息的最后一部分(“详细信息”)打印。
异常处理程序不仅处理在 try
子句中立即发生的异常,而且如果它们发生在 try
子句中调用(甚至间接)的函数内部。例如:
>>> def this_fails(): ... x = 1/0 ... >>> try: ... this_fails() ... except ZeroDivisionError as err: ... print('Handling run-time error:', err) ... Handling run-time error: division by zero
更多异常的处理请参照 官方异常处理文档
本文来自博客园,作者:wjxuriel,转载请注明原文链接:https://www.cnblogs.com/my-blog-site/p/16173299.html
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现