阅读 258

猪行天下之Python基础——6.1 异常与断言

内容简述:

  • 1、异常
  • 2、断言

1、异常

了解异常前,首先是区分「语法错误」与「运行时异常」,语法错误是连编译器都过不了的错误,比如if语句后面漏掉了冒号(:),程序跑都跑不起来;运行错误则是程序跑起来后,因为程序的业务逻辑问题引起的程序崩溃,比如除以0。


① Python中的常见异常

Exception类 因为是 所有异常类的父类,又称 万能异常,可以捕获任何异常!Python中常见的异常如下表所示:

异常 描述信息
AssertionError 断言语句失败
AttributeError 尝试访问未知的对象属性
IndexError 索引超出序列的范围
keyError 字典中查找一个不存在的Key
NameError 尝试访问一个不存在的变量
OSError 操作系统产生的异常,比如FileNotFoundError
SyntaxError Python语法错误
TypeError 不同类型间的无效操作
ZeroDivisionError 除数为0
IOError 输入输出错误
ValueError 函数传参类型错误

② 异常捕获

Python中为我们提供了两组语句用于异常捕获,try-expect-elsetry-finally。下面讲解下六种常见的玩法:

「1. try捕获了任何异常,直接丢给except后的代码块处理」,代码示例如下:

try:
    result = 1 / 0
except:
    print("捕获到异常了!")
复制代码

运行结果如下

捕获到异常了!
复制代码

「2. 捕获特定类型」,代码示例如下:

try:
    result = 1 / 0
except ZeroDivisionError:
    print("捕获到除数为零的错误"
复制代码

运行结果如下

捕获到除数为零的错误
复制代码

「3. 针对不同的异常设置多个except」,代码示例如下

运行结果如下

try:
    sum = 1 + '2'
    result = 1 / 0
except TypeError as reason:
    print("类型出错:" + str(reason))
except ZeroDivisionError as reason:
    print("除数为0:" + str(reason))
复制代码

运行结果如下

类型出错:unsupported operand type(s) for +: 'int' and 'str'
复制代码

「4. 对多个异常统一处理」,代码示例如下:

try:
    result = 1 / 0
    sum = 1 + '2'
except (TypeError, ZeroDivisionError) as reason:
    print(str(reason)) 
复制代码

运行结果如下

division by zero
复制代码

「5. 当没有检测到异常时才执行的代码块,可以用else」,代码示例如下:

try:
    result = 4 / 2
except ZeroDivisionError as reason:
    print(str(reason))
else:
    print("没有发生异常,输出结果:%d" % result)
复制代码

运行结果如下

没有发生异常,输出结果:2
复制代码

6. 无论是否发生异常都会执行的一段代码块」,代码示例如下:

try:
    result = 4 / 2
except ZeroDivisionError as reason:
    print(str(reason))
else:
    print("没有发生异常,输出结果:%d" % result)
finally:
    print("无论是否发生异常都会执行~")
复制代码

运行结果如下

没有发生异常,输出结果:2
无论是否发生异常都会执行。
复制代码

③ 异常抛出

Python为我们提供的都是异常都是在特定条件下才会触发的。而在一些特定的场景,某些操作可能会引起我们的业务异常,比如让用户输入一串手机号码,手机号码由一串0-9的数字构成,而如果用户输入了其他字符,显然是不合理的。我们可以通过正则对输入的手机号码进行校验,如果是手机号码就打印出来,不是的话则利用Python提供的raise关键字抛出一个ValueError异常。代码示例如下:

import re

# 注:这段正则你只需要知道是用来匹配电话号码的,正则在爬虫那里会详细讲解
phone_compile =re.compile(r'^(0|86|17951)?(13[0-9]|14[579]|15[0-35-9]|17[01678]|18[0-9])[0-9]{8}$')
number = input("请输入一串手机号码:")
if phone_compile.match(number) is not None:
    print("您输入的手机号码是:%s" % number)
else:
    raise ValueError
复制代码

运行结果如下

请输入一串手机号码:123456787
Traceback (most recent call last):
  File "F:/Project/Python/Book/Chapter 7/7_1_7.py", line 12in <module>
    raise ValueError
ValueError
复制代码

④ 自定义异常

上面通过raise关键字显式的抛出了一个内置的ValueError异常。如果程序里除了这个号码验证还有邮箱验证,我们又抛出一个这样的异常的话,会不利于异常的定位,异常是哪个地方引起的?对此,我们可以自定义异常,根据不同的错误抛出对应的异常。我们自定义一个非手机号码异常,代码示例如下:

# 自定义异常
class PhoneNumberException(Exception):
    def __init__(self, message):
        Exception.__init__(self)
        self.message = message

if __name__ == '__main__':
    phone_compile = re.compile(r'^(0|86|17951)?(13[0-9]|14[579]|15[0-35-9]|17[01678]|18[0-9])[0-9]{8}$')
    number = input("请输入一串手机号码:")
    if phone_compile.match(number) is not None:
        print("您输入的手机号码是:%s" % number)
    else:
        raise PhoneNumberException("非法的手机号码!")
复制代码

运行结果如下

请输入一串手机号码:1234
Traceback (most recent call last):
  File "F:/Project/Python/Book/Chapter 7/7_1_8.py", line 19in <module>
    raise PhoneNumberException("非法的手机号码!")
__main__.PhoneNumberException
复制代码

⑤ sys.exc_info()函数

除了前面介绍的获取异常信息的方式外,还可以通过sys模块里的exc_info()函数 获得,使用代码示例如下:

import sys

try:
    result = 1 / 0
except:
    tuple_exception = sys.exc_info()
# 输出结果依次是:异常类,类示例,跟踪记录对象
for i in tuple_exception:
    print(i)
复制代码

运行结果如下

<class 'ZeroDivisionError'>
division by zero
<traceback object at 0x000001E079360288>
复制代码

2、断言

assert关键字 后面的判断条件为假的时候,程序自动崩溃并抛出AssertionErro异常。一般在测试程序的时候才会用到:需要确保某个条件为真程序才能正常工作的时候使用

另外要和异常处理进行区分

异常处理」用于对程序发生异常情况的处理,以增加程序的健壮性和容错性,而「断言」则是用来检查非法情况,用于帮助开发者快速定位问题位置

Python中关于断言assert的玩法有两种:

  • assert 判断条件:如果判断条件为false,就raise一个AssertionError
  • assert 判断条件,异常描述:如果判断条件为false,就raise一个带描述信息的AssertionError

代码示例如下

a, b = 12

# 第一种断言用法
assert a > b
# 第二种断言用法
assert (a > b), ("{a} 并不比 {b} 大'".format(a = a, b = b))
复制代码

运行结果如下

Traceback (most recent call last):
  File "F:/Project/Python/Book/Chapter 7/7_1_10.py", line 5in <module>
    assert a > b
AssertionError

Traceback (most recent call last):
  File "F:/Project/Python/Book/Chapter 7/7_1_10.py", line 6in <module>
    assert (a > b), ("{a} 并不比 {b} 大'".format(a = a, b = b))
AssertionError: 1 并不比 2 大'
复制代码

如果本文对你有所帮助,欢迎
留言,点赞,转发
素质三连,谢谢😘~