异常处理

异常是指在程序发生错误的信号,程序一旦出现错误,便会产生一个异常,若程序没有处理它,就会抛出该异常,程序的运行也随之终止,异常一般分为语法错误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

无常
21 声望0 粉丝