零基础学 Python——异常处理

亲爱的亦菲彦祖们,欢迎继续跟随我们的编程学习之旅!在前两篇博客中,我们已经深入探讨了模块和包的概念与应用,帮助大家更好地组织和复用代码。今天,我们将迈入Python编程中的另一个重要领域——异常处理。掌握异常处理,不仅能让你的程序更加健壮和可靠,还能提升你的调试能力。让我们一起来揭开异常处理的神秘面纱吧!

一、了解异常

在编程过程中,**异常(Exception)**指的是程序运行中出现的错误,这些错误会导致程序的正常执行被中断。Python在检测到错误时,会抛出相应的异常,除非被捕获和处理,否则程序将会终止。

示例

尝试以只读模式打开一个不存在的文件,将会引发FileNotFoundError异常。

open('non_existent_file.txt', 'r')

运行上述代码,将得到如下错误提示:

Traceback (most recent call last):
  File "example.py", line 1, in <module>
    open('non_existent_file.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'non_existent_file.txt'

二、异常的基本语法

1. try-except结构

语法

try:
    # 可能发生错误的代码
except:
    # 如果发生异常执行的代码

示例

try:
    f = open('test.txt', 'r')
except:
    f = open('test.txt', 'w')

解释

  • try块中的代码可能会引发异常。
  • 如果发生任何异常,程序将跳转到except块执行相应的代码。

2. 捕获指定异常

为了更精确地处理不同类型的异常,可以指定要捕获的异常类型。

2.1 语法
try:
    # 可能发生错误的代码
except 异常类型:
    # 如果捕获到该异常类型执行的代码
2.2 示例
try:
    print(num)
except NameError:
    print('有错误:变量未定义。')

解释

  • 仅捕获NameError异常,如果发生其他类型的异常,则不会被捕获。
注意事项:
  1. 如果尝试执行的代码的异常类型与except指定的异常类型不一致,则该异常不会被捕获。
  2. 通常,try块中放置一行可能引发异常的代码。

3. 捕获多个异常

当需要捕获多个异常类型时,可以使用元组将异常类型括起来。

示例

try:
    print(1 / 0)
except (NameError, ZeroDivisionError):
    print('有错误:变量未定义或除以零。')

输出

有错误:变量未定义或除以零。

4. 捕获异常描述信息

可以通过as关键字获取异常的具体信息。

示例

try:
    print(num)
except (NameError, ZeroDivisionError) as result:
    print(result)

输出

name 'num' is not defined

5. 捕获所有异常

使用Exception作为基类,可以捕获所有类型的异常。

示例

try:
    print(num)
except Exception as result:
    print(result)

输出

name 'num' is not defined

三、异常的else和finally

1. 异常的else

else块用于在try块中没有发生异常时执行特定的代码。

语法

try:
    # 可能发生错误的代码
except Exception as e:
    # 发生异常时执行的代码
else:
    # 没有异常时执行的代码

示例

try:
    print(1)
except Exception as e:
    print(e)
else:
    print('我是else,当没有异常时执行的代码。')

输出

1
我是else,当没有异常时执行的代码。

2. 异常的finally

finally块中的代码无论是否发生异常,都会被执行,常用于资源的清理操作,如关闭文件。

语法

try:
    # 可能发生错误的代码
except Exception as e:
    # 发生异常时执行的代码
finally:
    # 无论是否异常都要执行的代码

示例

try:
    f = open('test.txt', 'r')
except Exception as e:
    f = open('test.txt', 'w')
else:
    print('没有异常,文件打开成功。')
finally:
    f.close()
    print('文件已关闭。')

解释

  • 如果文件存在,打开文件并打印“没有异常,文件打开成功。”,然后关闭文件。
  • 如果文件不存在,创建文件并关闭文件。

四、异常的传递

异常可以在多个嵌套的try-except块中传递,逐层处理。

示例

import time

try:
    f = open('test.txt', 'r')
    try:
        while True:
            content = f.readline()
            if len(content) == 0:
                break
            time.sleep(2)
            print(content)
    except:
        print('意外终止了读取数据。')
    finally:
        f.close()
        print('文件已关闭。')
except:
    print("没有这个文件。")

解释

  1. 外层try块尝试以只读模式打开test.txt文件。
  2. 如果文件不存在,将触发外层except块,打印“没有这个文件。”。
  3. 如果文件存在,内层try块开始读取文件内容。
  4. 在读取过程中,如果用户通过如Ctrl+C等方式中断程序,将触发内层except块,打印“意外终止了读取数据。”。
  5. 无论是否发生异常,finally块都会执行,关闭文件并打印“文件已关闭。”。

五、抛出异常

1. 使用raise主动抛出异常

在某些情况下,需要根据特定条件主动引发异常,以确保程序在不满足条件时停止执行。

示例

需求:用户输入密码,如果密码长度小于3位,则抛出异常并捕获。

def main():
    try:
        password = input('请输入密码:')
        if len(password) < 3:
            raise Exception(f'您输入的密码长度是{len(password)},密码不能少于3位。')
    except Exception as result:
        print(result)
    else:
        print('没有异常,密码输入完成。')

if __name__ == '__main__':
    main()

运行示例

请输入密码:ab
您输入的密码长度是2,密码不能少于3位。
请输入密码:abc
没有异常,密码输入完成。

2. 使用assert断言

assert语句用于在代码中设置断言,即在运行时检查某个条件是否为真。如果条件不满足,将抛出AssertionError异常。

示例

def read_file(file_path):
    assert isinstance(file_path, str), "文件路径必须是字符串类型。"
    try:
        with open(file_path, 'r') as f:
            content = f.read()
            return content
    except FileNotFoundError:
        print(f'文件"{file_path}"不存在。')
    except PermissionError:
        print(f'没有权限读取文件"{file_path}"。')

# 使用断言
read_file(123)  # 触发断言

输出

AssertionError: 文件路径必须是字符串类型。

解释

  • assert isinstance(file_path, str)检查file_path是否为字符串类型。
  • 如果条件不满足,抛出AssertionError并输出自定义错误信息。
  • assert通常用于调试阶段,确保代码逻辑的正确性。

六、自定义异常

在Python中,可以通过继承内置的异常类来创建自定义异常,以便在特定情况下提供更有意义的错误信息。

示例

创建一个自定义异常类PasswordTooShortError,用于处理密码长度不足的情况。

class PasswordTooShortError(Exception):
    """密码长度不足异常类"""
    def __init__(self, length, message="密码长度不足。"):
        self.length = length
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f"{self.message} 当前长度:{self.length}。"

def set_password(password):
    if len(password) < 3:
        raise PasswordTooShortError(len(password))
    print("密码设置成功。")

def main():
    try:
        pwd = input("请输入密码:")
        set_password(pwd)
    except PasswordTooShortError as e:
        print(e)
    except Exception as e:
        print(f"其他错误:{e}")
    else:
        print("没有异常,程序正常运行。")

if __name__ == "__main__":
    main()

运行示例

请输入密码:ab
密码长度不足。 当前长度:2。
请输入密码:abc
密码设置成功。
没有异常,程序正常运行。

解释

  • PasswordTooShortError继承自内置的Exception类。
  • set_password函数中,根据密码长度决定是否抛出自定义异常。
  • main函数中,捕获并处理PasswordTooShortError异常,提供更具体的错误信息。

总结

在本节中,我们全面探讨了Python异常处理的各个方面:

  • 了解异常:认识到异常是程序运行中的错误,并了解其对程序执行的影响。
  • 异常的基本语法:掌握了try-except结构,学习了如何捕获指定异常、多个异常以及所有异常。
  • 异常的else和finally:理解了else块在没有异常时执行代码的作用,以及finally块无论是否异常都要执行的特性。
  • 异常的传递:了解了异常在嵌套的try-except块中的传递机制。
  • 抛出异常:学习了如何使用raise主动抛出异常,以及使用assert设置断言。
  • 自定义异常:掌握了如何创建和使用自定义异常类,以提供更具描述性的错误信息。

通过掌握异常处理,亦菲彦祖们可以编写出更加健壮、可靠的Python程序,能够有效应对各种运行时错误,提升程序的稳定性和用户体验。下一篇博客中,我们将继续探索Python编程中的其他高级主题,敬请期待!

祝学习愉快,编程顺利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨胜增

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值