Python学习第七天

  1. 什么是异常,如何捕获处理异常,比如捕获“1除以0”的异常


    什么是异常?

    在编程中,异常(Exception) 是指在程序执行过程中发生的、打断正常程序流程的错误或事件。当异常发生时,如果程序没有采取措施进行处理,它通常会停止运行并显示错误信息。

    异常不是语法错误(Syntax Error),语法错误是在代码编译或解释阶段就发现的错误,比如你打错了关键字。异常是在程序运行时,因为某些不可预见的条件或情况(如文件不存在、网络中断、除数为零等)而导致的错误。

    例如,当你尝试:

    • 访问一个不存在的文件

    • 网络连接突然中断

    • 内存不足

    • 最常见的:用一个数字除以零

    这些情况下,Python 解释器会检测到一个异常,并“抛出”它。


    如何捕获和处理异常?

    在 Python 中,我们使用 try...except​ 语句来捕获(Catch) 和 处理(Handle) 异常。这样即使程序发生错误,也能优雅地继续运行,而不是直接崩溃。

    ​try...except​ 语句的基本结构如下:

    Python

    try:
        # 尝试执行可能引发异常的代码块
        # 如果这里的代码没有异常,except 块将被跳过
        # 如果发生异常,try 块中剩余的代码将被跳过,程序流程会跳转到 except 块
    except ExceptionType as e:
        # 当 try 块中发生 'ExceptionType' 类型的异常时,此处的代码将被执行
        # 'e' 是一个可选变量,用于引用捕获到的异常对象,你可以通过它获取异常的详细信息
        # 在这里处理异常,例如打印错误消息,记录日志,或者执行一些清理操作
    else:
        # (可选) 如果 try 块中的代码没有引发任何异常,则执行此处的代码
    finally:
        # (可选) 无论 try 块中是否发生异常,甚至在 except 或 else 块执行后,
        # finally 块中的代码总是会被执行
        # 通常用于执行清理操作,如关闭文件或网络连接
    

    捕获并处理“1 除以 0”的异常(ZeroDivisionError​)

    当你尝试用任何数字除以零时,Python 会抛出 ZeroDivisionError​ 异常。我们可以专门捕获这种类型的异常。

    示例代码:

    Python

    # 示例 1: 捕获特定的 ZeroDivisionError
    print("--- 示例 1: 捕获 ZeroDivisionError ---")
    try:
        numerator = 10
        denominator = 0
        result = numerator / denominator  # 这行代码会引发 ZeroDivisionError
        print(f"计算结果: {result}") # 这行代码将不会被执行
    except ZeroDivisionError:
        print("错误:不能除以零!请检查你的除数。")
    print("程序继续执行...\n") # 即使发生异常,程序也能继续执行
    
    # 示例 2: 捕获所有类型的异常(不推荐在生产代码中广泛使用)
    print("--- 示例 2: 捕获所有异常 (通用 Exception) ---")
    try:
        value = int("hello") # 这会引发 ValueError
        print(value)
    except Exception as e: # Exception 是所有内置异常的基类
        print(f"发生了一个通用错误: {e}")
        print(f"错误类型是: {type(e)}")
    print("程序继续执行...\n")
    
    # 示例 3: 捕获多个特定异常
    print("--- 示例 3: 捕获多个特定异常 ---")
    try:
        # test_case = 1 # 除以零
        # test_case = 2 # 类型转换错误
        test_case = 3 # 无错误
    
        if test_case == 1:
            res = 1 / 0
        elif test_case == 2:
            res = int("abc")
        else:
            res = "操作成功!"
        print(f"结果: {res}")
    except ZeroDivisionError:
        print("发生了除以零的错误!")
    except ValueError:
        print("发生了值转换错误(例如,尝试将非数字字符串转换为数字)!")
    except Exception as e: # 捕获其他任何未被上面捕获的异常
        print(f"发生了未预期的错误: {e}")
    print("程序继续执行...\n")
    
    # 示例 4: try...except...else...finally 完整结构
    print("--- 示例 4: 完整 try...except...else...finally 结构 ---")
    def divide_numbers(a, b):
        try:
            print(f"尝试计算 {a} / {b}...")
            result = a / b
        except ZeroDivisionError:
            print("错误:除数不能为零!")
            return None # 返回 None 表示失败
        except TypeError: # 例如,如果 a 或 b 不是数字
            print("错误:操作数类型不正确!")
            return None
        else: # 如果 try 块没有引发异常
            print("计算成功完成!")
            return result
        finally: # 无论是否发生异常,都会执行
            print("除法操作尝试结束。")
    
    print(f"10 / 2 = {divide_numbers(10, 2)}")
    print(f"10 / 0 = {divide_numbers(10, 0)}")
    print(f"'a' / 2 = {divide_numbers('a', 2)}")
    print("程序继续执行。\n")
    

    解释:

    1. ​try​ 块: 包含你认为可能出错的代码。Python 会尝试执行 try​ 块中的所有语句。

    2. ​except ZeroDivisionError:​: 如果在 try​ 块中发生了 ZeroDivisionError​ 类型的异常,那么 try​ 块的剩余部分会被跳过,并执行 except ZeroDivisionError:​ 下方的代码。

    3. ​except Exception as e:​: 这是捕获所有类型异常的通用方法。Exception​ 是所有内置异常的基类。使用 as e​ 可以让你访问异常对象本身,通常它包含错误信息。不建议仅仅使用 except Exception:​,因为它会捕获所有错误,包括你可能不希望捕获的编程错误(如 NameError​),这会掩盖真正的 bug。 应该尽可能地捕获特定类型的异常。

    4. 多个 except​ 块: 你可以为不同类型的异常定义多个 except​ 块。Python 会按顺序检查这些块,匹配到第一个符合的异常类型就执行相应的处理代码。

    5. ​else​ 块(可选): 如果 try​ 块中的代码没有引发任何异常,else​ 块中的代码就会被执行。这对于那些只在没有异常时才需要执行的操作很有用。

    6. ​finally​ 块(可选): 无论 try​ 块中是否发生异常,except​ 或 else​ 块是否执行,finally​ 块中的代码总是会被执行。它通常用于执行清理操作,例如关闭文件、释放资源、断开数据库连接等,以确保即使发生错误也能完成这些操作。

    通过恰当地使用 try...except...else...finally​,你的 Python 程序将更加健壮和可靠。