Python-异常处理
一、Python中常见的异常
异常 | 描述 |
---|---|
BaseException | 所有异常的基类 |
Exception | 常规错误的基类 |
NameError | 尝试访问一个没有声明的变量引发的错误 |
IndexError | 索引超出序列范围引起的错误 |
IndentationError | 缩进错误 |
ValueError | 传入无效的参数 |
KeyError | 使用映射中不存在的键引发的错误 |
IOError | 输入/输出操作错误 |
ImportError | 导入模块/对象失败 |
AttributeError | 对象没有这个属性引发的错误 |
TypeError | 类型不合适引发的错误 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
ZeroDivisionError | 除数为0引发的错误 |
AssertionError | 断言语句失败 |
SyntaxError | Python 语法错误 |
二、异常处理语句
1. try…except语句
try 语句的工作原理如下:
- 首先,执行 try 子句 (try 和 except 关键字之间的(多行)语句)。
- 如果没有触发异常,则跳过 except 子句,try 语句执行完毕。
- 如果在执行 try 子句时发生了异常,则跳过该子句中剩下的部分。 如果异常的类型与 except 关键字后指定的异常相匹配,则会执行 except 子句,然后跳到 try/except 代码块之后继续执行。
- 如果发生的异常与 except 子句 中指定的异常不匹配,则它会被传递到外部的 try 语句中;如果没有找到处理程序,则它是一个 未处理异常 且执行将终止并输出如上所示的消息。
try:
可能出现错误的代码块
except 异常类型:
try中一旦检测到异常,就执行这个位置的逻辑
在使用try…except语句捕获异常时,如果在except后面不指定异常名称,则表示捕获全部异常。
1.单分支
try:
ab
except NameError as e: #我们可以使用except与as+变量名 搭配使用,打印变量名会直接输出报错信息
print(e) #name 'ab' is not defined
2.多分支
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)=}")
运行结果:
OS error: [Errno 2] No such file or directory: 'myfile.txt'
Process finished with exit code 0
try 语句可以有多个 except 子句 来为不同的异常指定处理程序。 但最多只有一个处理程序会被执行。 处理程序只处理对应的 try 子句 中发生的异常,而不处理同一 try 语句内其他处理程序中的异常。 except 子句 可以用带圆括号的元组来指定多个异常,例如:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except (ValueError,OSError,BaseException) as e:
print(e)
运行结果:
[Errno 2] No such file or directory: 'myfile.txt'
Process finished with exit code 0
2. try…except…else语句
用于指定当try语句块中没有发现异常时要执行的语句;当try语句中发现异常时,else语句将不会被执行。
try:
for i in range(10):
int(i)
except IndexError as e:
print(e)
else:
print('***********') #*********** 执行了此处
#当try语句中的代码没有异常,被完整地执行完,就执行else中的代码
'''
***********
Process finished with exit code 0
'''
try:
b=10/0
except ZeroDivisionError as e:
print(e)
else:
print('***********') #*********** 执行了此处
#当try语句中的代码没有异常,被完整地执行完,就执行else中的代码
'''
division by zero
Process finished with exit code 0
'''
3. try…except…finally语句
如果存在 finally 子句,则 finally 子句是 try 语句结束前执行的最后一项任务。不论 try 语句是否触发异常,都会执行 finally 子句。
- 如果执行 try 子句期间触发了某个异常,则某个 except 子句应处理该异常。如果该异常没有 except 子句处理,在 finally 子句执行后会被重新触发。
- except 或 else 子句执行期间也会触发异常。 同样,该异常会在 finally 子句执行之后被重新触发。
- 如果 finally 子句中包含 break、continue 或 return 等语句,异常将不会被重新引发。
- 如果执行 try 语句时遇到 break,、continue 或 return 语句,则 finally 子句在执行 break、continue 或 return 语句之前执行。
- 如果 finally 子句中包含 return 语句,则返回值来自 finally 子句的某个 return 语句的返回值,而不是来自 try 子句的 return 语句的返回值。
>>> def bool_return():
... try:
... return True
... finally:
... return False
...
>>> bool_return()
False
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
4. 使用raise语句抛出异常
try:
raise TypeError('类型错误')
except Exception as e:
print(e)
'''
类型错误
Process finished with exit code 0
'''
raise 唯一的参数就是要触发的异常。这个参数必须是异常实例或异常类(派生自 Exception 类)。如果传递的是异常类,将通过调用没有参数的构造函数来隐式实例化:
raise ValueError # shorthand for 'raise ValueError()'
如果只想判断是否触发了异常,但并不打算处理该异常,则可以使用更简单的 raise 语句重新触发异常:
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise
运行结果:
Traceback (most recent call last):
File "E:/PC/untitled/练习/test.py", line 259, in <module>
raise NameError('HiThere')
NameError: HiThere
An exception flew by!
Process finished with exit code 1
5.用户自定义异常
class EvaException(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return self.msg
try:
raise EvaException('类型错误')
except EvaException as e:
print(e)
6.断言
assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。
assert的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题。格式如下:
assert expression [, arguments]
assert 表达式 [, 参数]
assert isinstance('1.23',float)
运行结果:
assert isinstance('1.23',float)
AssertionError
Process finished with exit code 1
7.异常链
参考官方文档:https://docs.python.org/zh-cn/3/tutorial/errors.html