异常处理
异常是指在程序发生错误的信号,程序一旦出现错误,便会产生一个异常,若程序没有处理它,就会抛出该异常,程序的运行也随之终止,异常一般分为语法错误SynataxError,这种错误应该在程序运行前就修改正确,另一种就是逻辑错误
1. 异常处理
语法
try:
被检测的代码块
except 异常类型:
检测到异常,就执行这个位置的逻辑
try:
print('start...')
print(x)
# 引用了一个不存在的名字,触发异常NameError
print('end...')
except NameError as e:
# as语法将异常类型的值赋值给变量e,这样我们通过打印e便可以知道错误的原因 print('异常值为:%s' %e)
print('run other code...')
# 执行结果为
start... 异常值为:name 'x' is not defined run other code...
被检测的代码块中异常发生位置之后的代码将不会执行,取而代之的是执行匹配异常的except子代码m模块,其余代码均正常运行
针对不同的异常处理
try:
# 被检测的代码块
pass
except NameError:
# 触发NameError时对应的处理逻辑
pass
except IndexError:
# 触发IndexError时对应的处理逻辑
pass
except KeyError:
# 触发KeyError时对应的处理逻辑
pass
示例
def convert_int(obj):
try:
res = int(obj)
except ValueError as e:
print('ValueError: %s' % e)
res = None
except TypeError as e:
print('TypeError: %s' % e)
res = None
return res
convert_int('egon')
# 结果: ValueError: invalid literal for int() with base 10: 'egon'
convert_int({'n': 1})
# 结果: TypeError: int() argument must be a string, a bytes-like object or a number, not 'dict'
多种异常优化
try:
# 被检测的代码块
pass
except (NameError, IndexError, TypeError):
# 触发NameError或IndexError或TypeError时对应的处理逻辑
pass
def convert_int(obj):
try:
res = int(obj)
except (ValueError, TypeError):
print('argument must be number or numeric string')
res = None
return res
convert_int('egon')
# 结果: argument must be number or numeric string
convert_int({'n': 1})
# 结果: argument must be number or numeric string
Exception
Exception是一种万能的异常处理类
try:
# 被检测的代码块
pass
except NameError:
# 触发NameError时对应的处理逻辑
pass
except IndexError:
# 触发IndexError时对应的处理逻辑
pass
except Exception:
# 其他类型的异常统一用此处的逻辑处理
pass
else
在多个 except 之后还可以跟一个 else (else必须跟在except 之后,不能单独存在),只有在被检测的代码块没有触发任何异常的情况下才会执行 else 的子代码块
try:
# 被检测的代码块
pass
except NameError:
pass
except IndexError:
pass
# ......
else:
# pass没有异常发生时执行的代码块
pass
finally
try还可以与 finally 连用,从语法上讲 finally 必须放到 else 之后,但可以使用 try-except-finally 的形式,也可以直接使用 try-finally 的形式,无论被检测的代码时候出发异常,都会执行 finally 的子代码块,因此通常 finally 的子代码块做一些回收资源的操作,比如关闭打开的文件,关闭数据库连接等
try:
# 被检测的代码块
pass
except IndexError:
pass
except NameError:
pass
# ......
else:
# 没有异常发生时执行的代码块
pass
finally:
# 无论有无异常发生都会执行的代码块
pass
raise
需要有程序要自己来明确的触发异常,这就用到了raise语句,raise后必须是一个异常的类或是异常的实例
class Student:
def __init__(self, name, age):
if not isinstance(name, str):
raise TypeError('name must be str')
if not isinstance(age, int):
raise TypeError('age must be int')
self.name = name
self.age = age
stu1 = Student(4573, 18) # TypeError: name must be str
stu2 = Student('egon', '18') # TypeError: age must be int
自定义异常类继承 Exception
# 自定义异常类,继承Exception
class ShortInputError(Exception):
def __init__(self, length, min_len):
self.length = length
self.min_len = min_len
# 设置抛出异常的描述信息
def __str__(self):
return f'你输入的长度是{self.length}, 不能少于{self.min_len}个字符'
def main():
try:
con = input('请输入密码:')
if len(con) < 3:
raise ShortInputError(len(con), 3)
except Exception as result:
print(result)
else:
print('密码已经输入完成')
main()
class PoolEmptyError(Exception):
# 可以通过继承Exception来定义一个全新的异常
def __init__(self, value='The proxy source is exhausted'):
# 可以定制初始化方法
super(PoolEmptyError, self).__init__()
self.value = value
def __str__(self):
# 可以定义该方法用来定制触发异常时打印异常值的格式
return '< %s >' % self.value
raise PoolEmptyError
# 结果: __main__.PoolEmptyError: < The proxy source is exhausted >
1.2 什么时候使用异常处理
如果错误发生的条件是 可知的 我们应该用if来进行预防
age = input('input your age>>: ').strip()
if age.isdigit(): # 可预知只有满足字符串age是数字的条件,int(age)才不会触发异常,
age = int(age)
else:
print('You must enter the number')
如果错误发生的条件是 不可预知,即异常一定会触发,那我们才应该使用异常处理机制,例如网络延时,数据库连接,等
import requests
from requests.exceptions import ConnectTimeout # 导入requests模块内自定义的异常
def get(url):
try:
response = requests.get(url, timeout=3) # 超过3秒未下载成功则触发ConnectTimeout异常
res = response.text
except ConnectTimeout:
print('连接请求超时')
res = None
except Exception:
print('网络出现其他异常')
res = None
return res
get('https://www.python.org')
2 断言
assert expression 断定表达式 expression 成立,否则触发异常 AssertionError,与raise-if-not的寓意相同,
assert 判断条件
age = '18'
# 若表达式isinstance(age,int)返回值为False则触发异常AssertionError
assert isinstance(age, int)
# 等同于
if not isinstance(age, int):
raise AssertionError
assert 判断条件,异常描述
age = '18'
# 若表达式isinstance(age,int)返回值为False则触发异常AssertionError
assert isinstance(age, int), (f'{age} must be int')
# 等同于
if not isinstance(age, int):
raise AssertionError