悠闲博客-blog.yxrjt.cn

Python异常处理与程序调试

更新时间:2025-07-01 00:00点击:62

前言

异常处理是程序用于处理以外情况的代码段,而在代码编写的过程中,经常要进行代码的调试和测试工作。本章将介绍 Python 语言中的异常处理和程序调试的具体使用方法。

一、异常处理

1.1、异常

补充:Exception 类是 Python 中大多数内置异常类的直接或间接父类。当你捕获 Exception 类型的异常时,实际上可以捕获大部分常见的异常情况,但不会捕获一些特殊的、不继承自 Exception 的异常,比如 SystemExit、GeneratorExit 和 KeyboardInterrupt 等。


在人们的工作生活中,做某一件事情的时候,通常并不能很顺序的完成,在做事情的过程中可能会有一些以外的情况发生。比如在开车上班的途中轮胎被扎漏气,就需要先补好车胎再去上班;再比如在写作业时笔坏了,就需要换一支新笔。所以当有意外情况发生时,就需要有对应的解决方法,以便使事情能够继续做下去。对于程序来说,当要完成某一件功能时,有可能也会产生一些以外的情况,这种意外发生的情况在程序中成为异常。

示例1:存在除数为 0 的程序代码示例如下:

print('开始执行除法运算/n/n')while True:    str1 = '输入 1 个整数作为第 1 个操作数/n'    str2 = '输入 2 个整数作为第 2 个操作数/n'    print('开始执行除法运算/n')    op1 = int(input(str1))    op2 = int(input(str2))    result = op1 / op2    print('%d / %d = %d' % (op1, op2, result))


  • 仔细阅读这段代码,并没有发现问题。只是在 while 循环进行除法的计算功能。但是请注意:当除数是 0 时,代码中的除法运算是没有意义的。u所以,在这段代码运行过程中,如果输入的第 2 个参数是0,则会出现异常情况,输出结果如下:

  • 开始执行除法运算输入 1 个整数作为第 1 个操作数3输入 2 个整数作为第 2 个操作数0Traceback (most recent call last):  File "D:/VS/Python/pythonProject/work.py", line 8, in <module>    result = op1 / op2             ~~~~^~~~~ZeroDivisionError: division by zero
  • 从程序输出结果中,可以发现:运行这段程序,键盘输入的第 2 个参数是 0 时,程序会产生一个 ZeroDivisionError 异常。Python 编译器将会输出提示信息“division by zero”,并终止程序的运行。就像汽车的车胎被扎一样,需要停下车先补好车胎才能继续开车。程序运行出现异常时,也需要做适当的处理,再继续完成所要实现的功能。一个健壮的程序,不能因为发生异常就中断结束。


  • 常见的异常现象有但不限于:读写文件时,文件不存在;访问数据库时,数据库管理系统没有启动;网络连接中断;算术运算时,除数为 0;序列越界等。


  • 异常(Exception)通常可看作是程序的错误(Error),是指程序是有缺陷(Bug)的。错误分为语法错误和逻辑错误。


  • 语法错误是值Python解释器无法解释代码,在程序执行前就可以进行纠正。逻辑错误是因为不完整或不合法的输入导致程序得不到预期的结果。程序在运行时,如果 Python 解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常。


  • 程序开发时,很难将所有的特俗情况都处理的面面俱到,通过异常捕获可以针对突发事件做集中的处理,从而保证程序的稳定性和健壮性。


  • 示例2:使用 try-except 语句捕获并处理除数为 0 的异常示例代码如下:

print('开始执行除法运算/n/n')while True:    str1 = '输入 1 个整数作为第 1 个操作数/n'    str2 = '输入 2 个整数作为第 2 个操作数/n'    try:        print('开始执行除法运算/n')        op1 = int(input(str1))        op2 = int(input(str2))        result = op1 / op2        print('%d / %d = %d' % (op1, op2, result))    except ZeroDivisionError:  # 捕获除数为 0 的异常        print('捕获除数为 0 的异常')
# 结果开始执行除法运算开始执行除法运算输入 1 个整数作为第 1 个操作数11输入 2 个整数作为第 2 个操作数0捕获除数为 0 的异常开始执行除法运算输入 1 个整数作为第 1 个操作数


在示例 2 中,当输入第 2 个参数为 0 时,程序继续到下一次循环执行,也就是异常情况得到了处理,程序并没有因为异常而终止。

这段代码以异常使用 try-except 的语法结果,对引发的异常进行捕获和处理,保证程序能继续执行并获得正确。由此得知,对异常进行处理要分为 2 个阶段,第一个阶段是捕获可能引发的异常,第二个阶段是要对发生的异常进行及时的处理。当异常发生时,不仅能检测到异常条件,还可以在异常发生时采取更可靠的补救措施,排除异常。

示例 1 和示例 2 中的 ZeroDivisionError 时除数为 0 的异常类,Python中还有很多内置的异常类,他们分别表示程序中可能发生的各种异常

异常处理语句主要有四种

示例库:在输入浮点数或除数为0时会异常

def division():    '''功能:分苹果'''    print("/n===================== 分苹果了 =====================/n")    apple = int(input("请输入苹果的个数:"))        # 输入苹果的个数    children = int(input("请输入来了几个小朋友:"))     result = apple//children                        # 计算每人分几个苹果    remain =apple-result*children                   # 计算余下几个苹果    if remain>0:        print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,              "个,剩下",remain,"个。")    else:        print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")if __name__ == '__main__':    division()                                      # 调用分苹果的函数

1. try...except :可以捕获异常并给出相应的处理结果


    语法:


        try:


            block1    #放入可能产生异常的代码


        except [ExceptionName [as alias]]   


                #[ExceptionName [as alias]]:指定要处理的异常,如果不指定则会会处理所有异常


                #[as alias]:给异常指定别名,它可以在输出异常内容时通过别名表示


            block2    #放入处理结果,如果block1出现异常就会执行block2中的代码


示例

def division():    '''功能:分苹果'''    print("/n===================== 分苹果了 =====================/n")    apple = int(input("请输入苹果的个数:"))                     # 输入苹果的个数    children = int(input("请输入来了几个小朋友:"))    if apple < children:        raise ValueError("苹果太少了,不够分...")    result = apple // children                                   # 计算每人分几个苹果    remain = apple - result * children                          # 计算余下几个苹果    if remain > 0:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result,              "个,剩下", remain, "个。")    else:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")if __name__ == '__main__':    try:                                                           # 捕获异常        division()                                                 # 调用分苹果的函数    except ZeroDivisionError:                                      # 处理除数为0的异常        print("/n出错了 ~_~ ——苹果不能被0个小朋友分!")    except ValueError as e:                                        # 处理值为浮点数的异常        print("/n出错了 ~_~ ——",e) #也可以一次指定多个异常# if __name__ == '__main__':#     try:                                        # 捕获异常#         division()                              # 调用分苹果的函数#     except (ZeroDivisionError,ValueError) as e:                   # 处理异常#         print(e)

2. try...except ...else:在捕获异常时对没有出现异常的情况进行处理


    语法:

        try:

            block1

        except [ExceptionName [as alias]]   

            block2

        else:

            block3    #没有抛出异常时才执行

示例        

def division():    '''功能:分苹果'''    print("/n===================== 分苹果了 =====================/n")    apple = int(input("请输入苹果的个数:"))                     # 输入苹果的个数    children = int(input("请输入来了几个小朋友:"))    if apple < children:        raise ValueError("苹果太少了,不够分...")    result = apple // children                                   # 计算每人分几个苹果    remain = apple - result * children                          # 计算余下几个苹果    if remain > 0:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result,              "个,剩下", remain, "个。")    else:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")if __name__ == '__main__':    try:                                        # 捕获异常        division()                              # 调用分苹果的函数    except (ZeroDivisionError,ValueError) as e:                   # 处理异常        print(e)    else:        print("分苹果顺利完成..")  #代码执行正常后再执行

3. try...except finally  #无论是否出现异常,都要执行一段固定的代码


    在实际项目开发中经常用来实现与关闭相关的操作,比如关闭文件


    语法:

        try:

            block1

        except [ExceptionName [as alias]]   

            block2

        finally:

            block3    

示例

def division():    '''功能:分苹果'''    print("/n===================== 分苹果了 =====================/n")    apple = int(input("请输入苹果的个数:"))                     # 输入苹果的个数    children = int(input("请输入来了几个小朋友:"))    if apple < children:        raise ValueError("苹果太少了,不够分...")    result = apple // children                                   # 计算每人分几个苹果    remain = apple - result * children                          # 计算余下几个苹果    if remain > 0:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result,              "个,剩下", remain, "个。")    else:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")if __name__ == '__main__':    try:                                        # 捕获异常        division()                              # 调用分苹果的函数    except (ZeroDivisionError,ValueError) as e:                   # 处理异常        print(e)    else:        print("分苹果顺利完成..")    finally:        print("进行了一次分苹果操作")


4. 使用raise语句抛出异常


    在程序开发时如果某个函数或方法可能会产生异常,但我们不想在当前的函数或方法当中来处理这个异常就可以使用raise语句在这个函数或方法当中来抛出异常,抛出异常后,后面的代码不会再执行


    语法:


        raise [ExceptionName[(reason)]]


                #[ExceptionName[(reason)]]:定义抛出的异常名称,如果省略此参数就会把当前的错误原样抛出


                #[(reason)]:异常信息的相关描述,如果省略此参数在抛出异常时就不会附带任何描述信息


        示例:模拟幼儿园分苹果(每个人至少分到一个)否则抛出异常

def division():    '''功能:分苹果'''    print("/n===================== 分苹果了 =====================/n")    apple = int(input("请输入苹果的个数:"))                      children = int(input("请输入来了几个小朋友:"))    if apple < children:        raise ValueError("苹果太少了,不够分...")    result = apple // children                                    remain = apple - result * children                              if remain > 0:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result,              "个,剩下", remain, "个。")    else:        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")if __name__ == '__main__':    try:                                               division()                                except (ZeroDivisionError,ValueError) as e:                      print(e)

程序调试:Python有两种常用调试方法

断点:在进行程序调试运行的时候想让程序在哪里停下来就在哪里设置断点,一个程序中可以设置多个断点


(1)使用python自带的IDLE进行程序调试

    打开调试功能:


        打开IDLE → Debug → Debugger


    debug控制台按钮作用:


        Globals:显示全局变量


        Go:继续执行


        Step:如果在设置的断点处调用了其他的函数,那么单机这个按钮会进入到函数的内部执行


        Over:单步执行


        Out:跳出函数与Step对应


        Quit:结束调试进行修改


    设置断点:


        光标放在要设置断点的行,鼠标右击选择 SetBreaKpoint


        设置好断点后按F5执行代码进行调试    


(2)使用assert断言语句调试程序

在 Python 中,assert是一个用于调试和测试的关键字,它主要用于对程序中的条件进行断言,即检查某个条件是否为真。


基本语法

assert语句的基本语法格式为:assert expression[, arguments]。其中,expression是一个表达式,其结果应该为True或False。arguments是可选的,用于在断言失败时提供额外的信息。


工作原理

如果expression的值为True,则assert语句不做任何事情,程序继续正常执行下一条语句。

如果expression的值为False,则assert语句会触发AssertionError异常,表明程序中出现了与预期不符的情况。如果指定了arguments,则会将arguments的值作为异常的参数传递,以便提供更详细的错误信息。

注意:python -O 文件名.py 命令行选项运行程序时,assert语句可能会被忽略,因此不应该使用assert来执行重要的程序逻辑或处理不可恢复的错误。


示例

验证传入的参数是否符合预期;


在编写测试用例时,验证函数或方法的返回值是否符合预期。


def divide(a, b):    assert b != 0, "除数不能为零"    return a / b def test_divide():    assert divide(10, 2) == 5,"1"    assert divide(5, 1) == 5,"2"    try:        assert divide(10, 1) == 0,"3"    except AssertionError as e:        print(f"测试失败: {e}") test_divide()

在那些循环或递归等复杂的程序执行过程中,应该始终保持为真的条件 


def factorial(n):    assert n >= 0, "输入必须是非负整数"    if n == 0 or n == 1:        return 1    else:        result = 1        for i in range(2, n + 1):            result *= i            assert result > 0, "阶乘结果应该始终为正"        return result

    


栏目分类

联系方式
  • help@yxrjt.cn
  • lgc@yxrjt.cn
  • admin@yxrjt.cn