Python小白到老司机,快跟我上车!基础篇(十五)

Posted coder-pig

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python小白到老司机,快跟我上车!基础篇(十五)相关的知识,希望对你有一定的参考价值。

异常与断言

1、异常

了解异常前,首先是区分「语法错误」与「运行时异常」,

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

① Python中的常见异常

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

异常描述信息
AssertionError断言语句失败
AttributeError尝试访问未知的对象属性
IndexError索引超出序列的范围
keyError字典中查找一个不存在的Key
NameError尝试访问一个不存在的变量
OSError操作系统产生的异常,比如FileNotFoundError
SyntaxErrorPython语法错误
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 12, in <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 19, in <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 = 1, 2

# 第一种断言用法
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 5, in <module>
    assert a > b
AssertionError

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

以上是关于Python小白到老司机,快跟我上车!基础篇(十五)的主要内容,如果未能解决你的问题,请参考以下文章

Python小白到老司机,快跟我上车!基础篇(十三)

Python小白到老司机,快跟我上车!基础篇

Python小白到老司机,快跟我上车!基础篇(十九)

Python小白到老司机,快跟我上车!基础篇(十九)

Python小白到老司机,快跟我上车!基础篇(二十)

Python小白到老司机,快跟我上车!基础篇(二十)