金丹期前期:1.9、python语言-python程序中的异常与捕获

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-17 08:11   48   0

一、异常简介

1、一个异常的例子

当如下的Python程序在运行时检测到一个错误,一般这时候解释器就无法继续执行代码了,会出现一些错误的提示,这就是所谓的"异常"。

#! /usr/bin/python3

print('========1========')
open('123.txt','r')
print('========2========')

出现错误:

================
Traceback (most recent call last):
  File "./8try.py", line 4, in <module>
    open('123.txt','r')
FileNotFoundError: [Errno 2] No such file or directory: '123.txt'

例如:读取一个不存在的文件或者用一个数除以0等错误都属于异常。

比较常见的异常类型如下:

AttributeError 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x

IOError 输入/输出异常;基本上是无法打开文件

ImportError 无法引入模块或包;基本上是路径问题或名称错误

IndentationError 语法错误(的子类) ;代码没有正确对齐

IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]

KeyError 试图访问字典里不存在的键

KeyboardInterrupt Ctrl+C被按下

NameError 尝试访问一个没有申明的变量

SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)

TypeError 传入对象类型与要求的不符合

UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它

ValueError 传入一个调用者不期望的值,即使值的类型是正确的

2、try...except捕获单个异常

把可能出现问题的代码,放在try中,把处理异常的代码,放在except中,修改代码成如下所示:

#! /usr/bin/python3

try:
        print('========1========')
        open('123.txt','r')
        print('========2========')
except IOError:
        print('========3========')

执行结果:

========1========
========3========

可以看出:其实代码执行到open函数是没有继续执行下去,然后执行到了处理异常的代码中了,这样至少代码不会中断了

3、try...except捕获多个异常

#! /usr/bin/python3

try:
        print('========1========')
#       open('123.txt','r')
        print('========2========')
        print(num)
        print('========3========')
except  (NameError, IOError):
        print('========4========')

运行结果如下:

========1========
========2========
========4========

关键词:多个异常时候,使用元组将它们组合起来

4、使用as获取捕获到的异常的基本信息

#! /usr/bin/python3

try:
        print('========1========')
#       open('123.txt','r')
        print('========2========')
        print(num)
        print('========3========')
except  (NameError, IOError) as result:
        print(result)

运行结果:

========1========
========2========
name 'num' is not defined

5、在try...except...中没有捕获到异常,那么就执行else中的代码

#! /usr/bin/python3

num = 100
try:
        print('========1========')
#       open('123.txt','r')
        print('========2========')
        print(num)
        print('========3========')
except  (NameError, IOError) as result:
        print(result)
else:
        print('=====NO ERROR======')

执行结果:

========1========
========2========
100
========3========
=====NO ERROR======

6、在try...except...中不管有没有捕获到异常,都执行finally中的代码

无异常的代码:

#! /usr/bin/python3

num = 100
try:
        print('========1========')
#       open('123.txt','r')
        print('========2========')
        print(num)
        print('========3========')
except  (NameError, IOError) as result:
        print(result)
else:
        print('=====NO ERROR======')
finally:
        print('======Forever=====')

有异常的代码:

#! /usr/bin/python3

#num = 100
try:
        print('========1========')
#       open('123.txt','r')
        print('========2========')
        print(num)
        print('========3========')
except  (NameError, IOError) as result:
        print(result)
else:
        print('=====NO ERROR======')
finally:
        print('======Forever=====')

执行结果都是

======Forever=====

二、异常的传递

主要是在函数嵌套和try...except嵌套中传递

#! /usr/bin/python3

def test1():
    print("----test1-1----")
    print(num)
    print("----test1-2----")


def test2():
    print("----test2-1----")
    test1()
    print("----test2-2----")


def test3():
    try:
        print("----test3-1----")
        test1()
        print("----test3-2----")
    except Exception as result:
        print("捕获到了异常,信息是:%s"%result)

    print("----test3-2----")



 test3()
 print("------华丽的分割线-----")
 test2()
  • 如果try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递。。。
  • 如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样
  • 注意观察上图中,当调用test3函数时,在test1函数内部产生了异常,此异常被传递到test3函数中完成了异常处理,而当异常处理完后,并没有返回到函数test1中进行执行,而是在函数test3中继续执行

三、自定义异常并抛出(raise)

你可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类.

#! /usr/bin/python3

class ShortInputException(Exception):
    '''自定义的异常类'''
    def __init__(self, length, atleast):
        #super().__init__()
        self.length = length
        self.atleast = atleast

def main():
    try:
        s = input('请输入 --> ')
        if len(s) < 3:
            # raise引发一个你定义的异常
            raise ShortInputException(len(s), 3)
    except ShortInputException as result:#x这个变量被绑定到了错误的实例
        print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (result.length, result.atleast))
    else:
        print('没有异常发生.')

main()

运行结果:

linbo@linbo-virtual-machine:~/python/python1$ ./9raise.py 
请输入 --> 12
ShortInputException: 输入的长度是 2,长度至少应是 3

四、在异常中抛出异常

有时候,捕获到了异常但是不想去处理这个异常,重新抛出去让另一层的异常处理函数去处理,示例代码如下:

#! /usr/bin/python3

class Test(object):
    def __init__(self, switch):
        self.switch = switch #开关
    def calc(self, a, b):
        try:
            return a/b
        except Exception as result:
            if self.switch:
                print("捕获开启,已经捕获到了异常,信息如下:")
                print(result)
            else:
                #重新抛出这个异常,此时就不会被这个异常处理给捕获到,从而触发默>认的异常处理
                raise


a = Test(True)
a.calc(11,0)

print("----------------------华丽的分割线----------------")

a.switch = False
a.calc(11,0)

运行结果如下:

捕获开启,已经捕获到了异常,信息如下:
division by zero
----------------------华丽的分割线----------------
Traceback (most recent call last):
  File "./9raise.py", line 24, in <module>
    a.calc(11,0)
  File "./9raise.py", line 8, in calc
    return a/b
ZeroDivisionError: division by zero

关键词:上面程序使用switch打开与关闭处理异常,在关闭异常处理时,捕获到之后直接又抛出了。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP