python程序调试和异常处理

程序异常

        有时程序错误称为程序异常,相信每一位写程序的人一定会碰上程序错误,过去碰上这类情况将终止执行,同时出现错误信息,错误信息内容通常显示Traceback,然后列出异常报告。Python提供的功能可以让我们捕捉异常和撰写异常处理程序,当发生异常时被我们捕捉到则会去执行异常处理程序,然后程序可以继续执行。

设计一个程序异常

以一个除数为0的错误开始说明。

实例1

例子:def division(x, y):

                 return x / y

           print(division(10, 2))

           print(division(5, 0))

           print(division(6, 3))

执行结果:
Traceback (most recent call last):
  File "C:/Users/mac/PycharmProjects/pythonProject/main.py", line 4, in
    print(division(5, 0))
  File "C:/Users/mac/PycharmProjects/pythonProject/main.py", line 2, in division
    return x / y
ZeroDivisionError: division by zero

5.0

        上述程序在执行第3行时,一切还是正常。但是执行第4行,因为第2个参数是0,导致ZeroDivisionError: division by zero的错误,所以整个程序执行终止。其实对于上述程序而言,若是程序可以执行第5行,是可以正常得到执行结果的,可是程序第4行已经造成程序终止了,所以无法执行第5行。

撰写异常处理程序

try - except

        发生异常被捕捉时程序会执行异常处理程序,然后跳开异常位置,再继续往下执行。这时要使用try - except指令,它的语法格式如下:

try:

        指令                        # 预先设想可能引发错误异常的指令

except 异常对象1:          # 若以以上执行结果来说,异常对象就是指ZeroDivisionError

        异常处理程序1       # 通常是指出异常原因,方便修正

上述会执行try:下面的指令,如果正常则跳离except部分,如果指令异常,则检查此异常是否是异常对象所指的错误;如果是,代表异常被捕捉了,则执行此异常对象下面的异常处理程序。

重新设计实例1,增加异常处理程序

实例2

def division(x, y):

        try:

                return x / y

        except ZeroDivisionError:

                print("除数不可为0")

print(division(10, 2))

print(division(5, 0))

print(division(6, 3))

执行结果:

5.0
除数不可为0
None
2.0

        上述程序执行第6行时,会将参数(10,2)带入division()函数,由于执行try的指令的 “x/y” 没有问题,所以可以执行 “return x / y”,这是Python将跳过except的指令。当程序执行第7行时,会将参数(5,0)带入division()函数,由于执行try的指令的 “x / y” 产生了除数为0的ZeroDivisionError异常,这时Python会寻找是否有处理这类异常的except ZeroDivisionError存在,如果有就表示此异常被捕捉,就去执行相关的错误处理程序,此例是执行第5行,输出“除数不可为0”的错误。函数返回然后输出结果None,None是一个对象,表示结果不存在,最后返回程序第8行,继续执行相关指令。

        从上述案例可以看到,程序增加了try - except后,若是异常问题被except捕捉,则出现的异常信息比较好处理,同时不会有程序中断的情况发生。

        特别需要留意的是在try - except的使用中,如果在try:后面的指令产生异常,则这个异常不是我们设计的except异常对象,表示异常没被捕捉到,这时程序依旧会像实例1一样,直接出现错误信息,然后程序终止。

重新设计实例2,但在程序第9行使用字符呼叫除法运算,造成程序异常。

实例3

def division(x, y):

        try:

                return x / y

        except ZeroDivisionError:

                print("除数不可为0")

print(division(10, 2))

print(division('a', 'b'))

print(division(6, 3))

执行结果:

5.0
Traceback (most recent call last):
  File "C:/Users/mac/PycharmProjects/pythonProject/main.py", line 7, in
    print(division('a', 'b'))
  File "C:/Users/mac/PycharmProjects/pythonProject/main.py", line 3, in division
    return x / y
TypeError: unsupported operand type(s) for /: 'str' and 'str'

        由上述执行结果可以看到异常原因是TypeError,由于我们在程序中没有设计except TypeError的异常处理程序,所以程序会终止执行。要解决这类问题需要多设计一组try - except。

        扩充设计实例3,增加TypeError异常的捕捉

实例4

def division(x, y):

        try:

                return x / y

        except ZeroDivisionError:

                print("除数不可为0")

        except TypeError:

                print("除法数据型态不符")

print(division(10, 2))

print(division('a', 'b'))

print(division(6, 3))

执行结果:

5.0
除法数据型态不符
None
2.0

try - except - else

        Python在try - except中又增加了else指令,这个指令存放的主要目的是try内的指令正确时,可以执行else内的指令区块,我们可以将这部分指令区块称为正确处理程序,这样可以增加程序的可读性。语法格式如下:

try:

        指令

except 异常对象1:

        异常处理程序1

    else:

正确处理程序

使用try - except - else重新设计实例3

实例5

def division(x, y):

        try:

                ans = x / y

        except ZeroDivisionError:

                print("除数不可为0")

       else:

                return ans

print(division(10, 2))

print(division(5, 0))

print(division(6, 3))

执行结果:与实例2相同

找不到文档的错误FileNotFoundError

程序设计时经常发生的异常是打开文档时找不到文档,这是会有FileNotFoundError异常。

实例6

fn = 'data.txt'

try:

        with open(fn) as file_Obj:

                data = file_Obj.read()

except FileNotFoundError:

        print("找不到 %s 文档" % fn)

else:

        print(data)

执行结果:

找不到 data.txt 文档

常见的异常对象

AttributeError 通常是指对象没有这个属性
Exception 一般错误皆可用
FileNotFoundError 找不到open()打开的文档
IOError 在输入或输出时发生错误
IndexError 索引超出范围区间
KeyError 在映射中没有这个键
MemoryError 需求内存空间超出范围
NameError 对象名称未声明
SyntaxError 语法错误
SystemError 直译器的系统错误
TypeError 数据类型错误
ValueError 输入无效参数
ZeroDivisionError 除数为零

finally

        Python的关键词finally的功能是和try配合使用,在try之后可以有except或else,这个finally关键词必须放在except和else之后,不论是否有异常发生,一定会执行这个finally内的程序代码。

try:

        指令

except 异常对象:

        异常处理程序

finally:

        一定会执行

这个功能主要是用在Python程序与数据库连接时,输出连接相关信息。

try - except - finally的应用,读者可以发现无论是否有异常,都会执行finally

实例7

def division(x, y):

        try:

                return x / y

        except:

                print("异常发生")

        finally:

                print("阶段任务完成")

print(division(10, 2),"\n")

print(division(5, 0),"\n")

print(division('a', 'b'),"\n")

print(division(6, 3),"\n")

执行结果:

阶段任务完成
5.0 

异常发生
阶段任务完成
None 

异常发生
阶段任务完成
None 

阶段任务完成
2.0 

        上述程序执行时,如果没有发生异常,则程序会先输出字符串“阶段任务完成”然后返回主程序,输出division()的返回值。如果程序有异常则会先输出字符串“异常发生”,再执行finally的程序代码输出字符串“阶段任务完成”,然后返回主程序输出“None”。

你可能感兴趣的:(python)