Python基础 - 异常处理

异常处理, 平时用得非常多的, 即便程序的逻辑很简单, 但总是要考虑各种各样的情况出现, 为了使得程序更加健壮, 异和用户体验更好, 异常处理是必须掌握的. 同时, 在调试的时候, 捕捉异常也是一种最为常见的 找 bug 的方式呀.

场景无非就两个:

  • 尝试捕捉异常: try ... except , 一般用万能的异常类 Exception
  • 主动抛出异常: raise .....

常见异常

2 / 0
---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

<ipython-input-2-8b4ac6d3a3e1> in <module>
----> 1 2 / 0


ZeroDivisionError: division by zero
2 + 'a'
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-3-1bab65faeb88> in <module>
----> 1 2 + 'a'


TypeError: unsupported operand type(s) for +: 'int' and 'str'
{3, 4, 5} * 3
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-4-d7437368bfef> in <module>
----> 1 {3, 4, 5} * 3


TypeError: unsupported operand type(s) for *: 'set' and 'int'
print(cj)
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-5-230235b96338> in <module>
----> 1 print(cj)


NameError: name 'cj' is not defined
f = open('xxx.txt')
---------------------------------------------------------------------------

FileNotFoundError                         Traceback (most recent call last)

<ipython-input-6-82a0b92d4a44> in <module>
----> 1 f = open('xxx.txt')


FileNotFoundError: [Errno 2] No such file or directory: 'xxx.txt'
len(3)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-7-6b3b01eb5e19> in <module>
----> 1 len(3)


TypeError: object of type 'int' has no len()
list(3)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-8-f0568a1336f0> in <module>
----> 1 list(3)


TypeError: 'int' object is not iterable

异常处理结构

基本思路:先尝试运行代码,如果没有问题就正常执行,如果发生错误就尝试去捕获和处理,最后实在没有办法了才程序崩溃,从某个角度看,异常处理结构也属于选择结构的变形

try - except

try:
    # 可能会依法异常的代码,先执行以下试试
except Exception [as reason]:
    # 如果try 中的代码抛出异常,并被except捕获,就执行这里的代码
# 要求用户必须输入整数,不接受任何其他类型输入
while True:
    try:
        x = int(input("Please enter an integer: "))
        
        print("You have input {0}".format(x)) # 我还是喜欢用 "You have input %d" % x
        break
        
    except Exception as result:
        print(result)
        print("Error")
Please enter an integer: vv
Erro
Please enter an integer: cj
Erro
Please enter an integer: 666
You have input 666

try - except - else

没有异常,执行else,异常则不走else, 类似 for/while - else 结构

try:
    # 可能会引发异常的代码
except Exception [as result]:
    # 用来处理异常的代码
else:
    # 如果没有异常,就执行else, 否则不执行else
    

注意:不要把太多的代码放在try中,而是放真正可能会引发异常的代码

while True:
    x = input("Please enter an integer: ")
    try:
        x = int(x)  # 这才是最可能出错的地方
    except Exception as result:
        print("Error")
    else:  # 没有异常
        print("You have input %d" % x)
        break  # 输入正确,退出循环
        
Please enter an integer: cj
Error
Please enter an integer: 666
You have input 666

try - except - finally

不论异常否,最后都会被执行,可用来做一些清理工作如,释放try代码申请的资源等等

try:
    # 可能会引起异常的代码
except Exception:
    # 处理异常的代码
finally:
    # 不论try是否异常,都会执行这里的代码
def div(a, b):
    try:
        print(a / b)
    except Exception:
#     except ZeroDivisionError:
        print('Error')
    finally:
        print("Anyway,i still say: 'hello world'")
        
div(3, 0)
Error
Anyway,i still say: 'hello world'

finally 子句也会发生异常

可做多种异常的异常处理结构

try:
    # 可能会引起异常的代码
except Exception1:
    # 处理异常类型1的代码
except Exception2:
    # 处理异常类型2的代码
.....
except Exceptiongn:
    # 处理异常类型n的代码
try:
    x = float(input('请输入被除数:'))
    y = float(input("请输入除数: "))
    z = x / y
except ZeroDivisionError:
    print("除数不能为0")
except TypeError:
    print("二者都应为数值类型")
except NameError:
    print("变量不存在")
else:
    print(x, '/', y, '=', z)
请输入被除数:8
请输入除数: b



---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-2-97c20fa0afa5> in <module>
      1 try:
      2     x = float(input('请输入被除数:'))
----> 3     y = float(input("请输入除数: "))
      4     z = x / y
      5 except ZeroDivisionError:


ValueError: could not convert string to float: 'b'

自定义异常类

num = input("请输入手机号:")

# 生成一个类,这个类可以用于保存异常的名字;必须要传Exception形参
class Phone(Exception):
    pass


try:
    if len(num) != 11:
        # raise 定义异常的提示信息    异常类(提示的信息)
        raise Phone("长度不够11位")  # 给Phone异常,改变提示的信息
except Exception as result:
    print(result)  # result就是phone里面的提示语,是我们自定义的

# 什么时候用if?判断程序,确保里面程序不会有问题的时候
# 什么时候用try?觉得某段代码会报错才用try
class Div(Exception):
    pass


try:
    x = float(input('请输入被除数:'))
    y = float(input("请输入除数: "))
    z = x / y
    raise Div("出错了哦, 好好检查下呢")
    
except Exception as result:
    print(result)
else:
    print(x, '/', y, '=', z)
请输入被除数:x
could not convert string to float: 'x'

断言assert 与上下文管理语句

assert 语句常用来在程序的某个位置确认某个条件必须满足.
assert仅当脚本的__ debug __ 属性值为True 时有效,一般只在开发和测试阶段使用,(程序编译为字节码时,assert语句将被删除

a = 3
b = 5
assert a == b, 'a must be equal to b'
---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

<ipython-input-9-2784da305078> in <module>
      1 a = 3
      2 b = 5
----> 3 assert a == b, 'a must be equal to b'


AssertionError: a must be equal to b

小结

  • 程序出错是一件非常难以避免的事情

  • 异常一般指程序运行时发生的错误

  • 程序运行时出现错误会自动引发异常,程序员可通过raise语句显式引发异常

  • 合理使用异常结构try-except-else-finally 可以使得程序更加健壮

  • try - except - else, 当程序异常则不会执行else; finally, 不论怎样都会执行,可用来清理try代码块的空间等工作

猜你喜欢

转载自www.cnblogs.com/chenjieyouge/p/12343374.html