找回密码
 立即注册
首页 业界区 安全 [Python] Python 异常处理机制

[Python] Python 异常处理机制

倡遍竽 2025-6-1 21:28:29
概述ython 异常处理机制

什么是异常,什么是异常程序?

异常:程序正常执行过程中出现的不正常的情况,该情况影响了程序的正常执行。
异常程序:是指程序执行的非法指令,比如常见的非法操作码,地址越界,算术溢出等,异常程序的出现一般有两种情况:

  • 程序设计时的编程错误或程序运行时的硬件错误
  • 精心设计地入侵系统程序(病毒)
异常抛出

语法: raise {exception} | 抛出异常


  • 用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类。
  • 抛出异常和自定义异常
Python用异常对象(exception object)表示异常情况,遇到错误后,会引发异常。
如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行。


  • Python中的raise 关键字用于引发一个异常,基本上和C#和Java中的throw关键字相同,如下所示:
  1. def ThorwErr():
  2.     raise Exception("抛出一个异常")
  3. # Exception: 抛出一个异常
  4. ThorwErr()
复制代码

  • raise关键字后面是抛出是一个通用的异常类型(Exception),一般来说抛出的异常越详细越好,Python在exceptions模块内建了很多的异常类型,通过使用dir函数来查看exceptions中的异常类型,如下:
  1. import exceptions
  2. # ['ArithmeticError', 'AssertionError'.....]
  3. print dir(exceptions)
复制代码
异常捕获与处理

简述


  • 异常处理是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况,即超出程序正常执行流程的某些特殊条件。
  • Python提供了两个非常重要的功能来处理程序在运行中出现的异常和错误。经常使用的是try...except语句,拓展一下就是try-except-else-finally,另一个是断言(这个后面再讲)。

    • try:正常情况下,程序计划执行的语句。
    • except:程序异常是执行的语句。
    • else:程序无异常即try段代码正常执行后会执行该语句。
    • finally:不管有没有异常,都会执行的语句。

语法 : try-except-else-finally

Python用异常对象(exception object)表示异常情况,遇到错误后,会引发异常。
如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行。
name为异常类型,可指定可不指定:
  1. try:
  2.     # 代码段1
  3.     pass
  4. except {name}:
  5.     # 代码段2
  6.     pass
  7. else:
  8.     # 代码段3
  9.     pass
  10. finally:
  11.     # 代码段4
  12.     pass
复制代码
常见异常


  • TypeError
当操作或函数应用于不适当类型的对象时引发。
例如: a = 5 + '10' 这个例子中,我们试图将整数5和字符串'10'相加,这是不允许的,因为它们是不同的类型


  • KeyError
当尝试访问字典中不存在的键时引发。
例如: d = {'a': 1, 'b': 2} print(d['c'])
这个例子中,我们试图访问字典d中不存在的键'c',因此会引发KeyError异常
1.png


  • ValueError
当函数或操作的参数具有正确的类型但不合法时引发。
例如: int('abc') 这个例子中,我们试图将字符串'abc'转换为整数,但是'abc'不是一个有效的整数,因此会引发ValueError异常
2.png

3.png

4.png


  • NameError
    当尝试访问一个未定义的变量时,会抛出NameError异常。
例如: print(x) 这个例子中,我们尝试打印变量x的值,但是x没有被定义,因此会引发NameError异常


  • IndexError
当尝试访问列表、元组或字符串中不存在的索引时引发。
例如: a = [1, 2, 3] print(a[3]) 这个例子中,我们试图访问列表a的第四个元素,但是a只有三个元素,因此会引发IndexError异常


  • ZeroDivisionError
当尝试除以零时引发。
例如: a = 5 / 0 这个例子中,我们试图将5除以0,这是不允许的,因为除数不能为零,因此会引发ZeroDivisionError异常
  1. try:
  2.     x = 1 / 0
  3. except ZeroDivisionError:
  4.     print("除零错误!")
复制代码

  • IOError
当尝试读取不存在的文件或无法访问文件时引发。
例如: f = open('nonexistent_file.txt', 'r') 这个例子中,我们试图打开一个不存在的文件nonexistent_file.txt,因此会引发IOError异常


  • ImportError
当尝试导入不存在的模块或包时引发。
例如: import nonexistent_module 这个例子中,我们试图导入一个不存在的模块nonexistent_module,因此会引发ImportError异常


  • AttributeError
当尝试访问对象不存在的属性时引发。
例如: s = 'hello' print(s.uppercase()) 这个例子中,我们试图调用字符串s的不存在的方法uppercase(),因此会引发AttributeError异常


  • KeyboardInterrupt
当用户中断程序执行时引发。
例如: while True: try: x = input('Enter a number: ') break except KeyboardInterrupt: print('You pressed Ctrl+C!') > 这个例子中,如果用户按下Ctrl+C,程序会引发KeyboardInterrupt异常,我们可以捕获这个异常并打印一条消息


  • PermissionError: [Errno 13] Permission denied
  • open(filePath)中的filePath是一目录路径,而非目录路径
  • 先前打开的file文件对象未被关闭
实践案例

重要结论


  • 无论有无异常,finally代码段一定会被执行
  • 若有异常,则执行except代码段
  • 若无异常且无return,则执行else代码段
  • 若无异常且有return, try代码段中有return 语句, 则else代码段不会被执行
  • 若无异常且有return, try代码段没有return语句,则else代码段会执行
CASE 无return

除数为0.0 : 不使用try的话程序会报错直接退出
  1. a = 5.0 / 0.0
  2. print('输出:我是try')
  3. # ZeroDivisionError: float division by zero
  4. try:
  5.     a = 5.0 / 0.0
  6.     print('输出:我是try')
  7. except :
  8.     print('输出:我是except')
  9. # 输出:我是except
复制代码
加上else和finally,执行逻辑:try-->except-->finally
  1. try :
  2.     a = 5.0 / 0.0
  3.     print('输出:我是try')
  4. except :
  5.     print('输出:我是except')
  6. else :
  7.     print('输出:我是else')
  8. finally :
  9.     print('输出:finally')
  10.    
  11. # 输出:我是except
  12. # 输出:finally
复制代码
除数为1.0 : 即正常程序

执行逻辑:try-->else-->finally
  1. try :
  2.     a = 5.0 / 1.0
  3.     print('输出:我是try')
  4. except :
  5.     print('输出:我是except')
  6. else :
  7.     print('输出:我是else')
  8. finally :
  9.     print('输出:finally')
  10. # 输出:我是try
  11. # 输出:我是else
  12. # 输出:finally
复制代码
CASE 有return,较为复杂,需仔细判别

除数为0.0 : 有异常时,finally 的 return 优先级 > except 的 return 优先级

执行逻辑:try-->except-->finally
  1. def test():
  2.     try :
  3.         a = 5.0 / 0.0
  4.         print('输出:我是try')
  5.         return 0
  6.     except :
  7.         print('输出:我是except')
  8.         return 1
  9.     else :
  10.         print('输出:我是else')
  11.         return 2
  12.     finally :
  13.         print('输出:finally')
  14.         return 3
  15. print('test: ',test())
  16. # 输出:我是except
  17. # 输出:finally
  18. # test: 3
复制代码
程序在except内部虽然已经return了,但是finally依然会被执行,此时finally亦有return,则输出为finally代码段的返回值。
执行逻辑:try-->except-->finally,返回except代码段返回值
  1. def test():
  2.     try :
  3.         a = 5.0 / 0.0
  4.         print('输出:我是try')
  5.         return 0
  6.     except :
  7.         print('输出:我是except')
  8.         return 1
  9.     else :
  10.         print('输出:我是else')
  11.         return 2
  12.     finally :
  13.         print('输出:finally')
  14. print('test: ',test())
  15. # 输出:我是except
  16. # 输出:finally
  17. # test: 1
复制代码
程序在except内部虽然已经return了,但是finally依然会被执行,此时finally内部没有return,则最终输出except代码段的返回值。
除数为1.0 : 无异常时, finally 的 return 优先级  > try 的 return 优先级

执行逻辑:try-->else-->finally
  1. def test():
  2.     try :
  3.         a = 5.0 / 1.0
  4.         print('输出:我是try')
  5.         return 0
  6.     except :
  7.         print('输出:我是except')
  8.         return 1
  9.     else :
  10.         print('输出:我是else')
  11.         return 2
  12.     finally :
  13.         print('输出:finally')
  14.         return 3
  15. print('test: ',test())
  16. # 输出:我是try
  17. # 输出:finally
  18. # test: 3
复制代码
程序在try内部虽然已经return了,但是else和finally依然会被执行,此时finally有return,则输出为finally代码段的返回值。
执行逻辑:try-->finally,返回try代码段返回值
  1. def test():
  2.     try :
  3.         a = 5.0 / 1.0
  4.         print('输出:我是try')
  5.         return 0
  6.     except :
  7.         print('输出:我是except')
  8.         return 1
  9.     else :
  10.         print('输出:我是else')
  11.         return 2
  12.     finally :
  13.         print('输出:finally')
  14.         # return 3
  15. print('test: ',test())
  16. # 输出:我是try
  17. # 输出:finally
  18. # test: 0
复制代码
程序在try内部已经return了,else不会被执行,finally会被执行,此时finally没有return,则输出为try代码段的返回值。
执行逻辑:try-->else-->finally,返回else代码段返回值
  1. def test():
  2.     try :
  3.         a = 5.0 / 1.0
  4.         print('输出:我是try')
  5.         # return 0
  6.     except :
  7.         print('输出:我是except')
  8.         return 1
  9.     else :
  10.         print('输出:我是else')
  11.         return 2
  12.     finally :
  13.         print('输出:finally')
  14.         # return 3
  15. print('test: ',test())
  16. # 输出:我是try
  17. # 输出:我是else
  18. # 输出:finally
  19. # test: 2
复制代码
程序在try内部无return,else将会被执行,finally也会被执行,此时finally没有return,则输出为else代码段的返回值。
CASE 捕获多个异常


  • 可以在一个try块中捕获多个异常,通过在多个except块中指定不同的异常类型来实现。
  1. try:
  2.     x = int(input("请输入一个整数:"))
  3.     y = 1 / x
  4. except ValueError:
  5.     print("输入的不是一个整数!")
  6. except ZeroDivisionError:
  7.     print("输入的整数不能为零!")
复制代码
CASE 捕获所有异常

可以通过捕获基类Exception来捕获所有异常,但这是一种不推荐的做法,除非在特定情况下确实需要捕获所有可能的异常。
  1. try:
  2.     x = 1 / 0
  3. except Exception as e:
  4.     print("发生异常:", e)
复制代码
CASE 自定义异常


  • 可以通过创建自定义异常类来定义自己的异常类型,通常自定义异常类继承自Exception类。
  1. class MyCustomError(Exception):
  2.     pass
  3. try:
  4.     raise MyCustomError("这是一个自定义异常")
  5. except MyCustomError as e:
  6.     print("捕获自定义异常:", e)
复制代码
CASE 综合案例

展示了如何使用异常处理来实现一个简单的计算器程序。程序能够处理用户输入错误、除零错误以及文件读写错误。
  1. class Calculator:
  2.     def add(self, a, b):
  3.         return a + b
  4.     def subtract(self, a, b):
  5.         return a - b
  6.     def multiply(self, a, b):
  7.         return a * b
  8.     def divide(self, a, b):
  9.         try:
  10.             return a / b
  11.         except ZeroDivisionError:
  12.             print("除零错误!")
  13.             return None
  14. def log_activity(func):
  15.     def wrapper(*args, **kwargs):
  16.         try:
  17.             result = func(*args, **kwargs)
  18.             return result
  19.         except Exception as e:
  20.             print(f"执行{func.__name__}时发生异常:", e)
  21.             return None
  22.     return wrapper
  23. @log_activity
  24. def main():
  25.     calc = Calculator()
  26.     try:
  27.         a = float(input("请输入第一个数:"))
  28.         b = float(input("请输入第二个数:"))
  29.     except ValueError:
  30.         print("输入的不是一个有效的数字!")
  31.         return
  32.     operation = input("请选择操作(+,-,*,/):")
  33.    
  34.     if operation == '+':
  35.         result = calc.add(a, b)
  36.     elif operation == '-':
  37.         result = calc.subtract(a, b)
  38.     elif operation == '*':
  39.         result = calc.multiply(a, b)
  40.     elif operation == '/':
  41.         result = calc.divide(a, b)
  42.     else:
  43.         print("无效的操作!")
  44.         return
  45.     if result is not None:
  46.         print(f"结果是:{result}")
  47.    
  48.     try:
  49.         with open('result.txt', 'a') as file:
  50.             file.write(f"{a} {operation} {b} = {result}\n")
  51.     except IOError:
  52.         print("文件写入失败!")
  53.     finally:
  54.         print("计算器程序结束。")
  55. if __name__ == "__main__":
  56.     main()
复制代码

  • 示例解释:

    • Calculator 类:实现基本的加减乘除运算。

      • add, subtract, multiply, divide 方法分别实现加法、减法、乘法和除法运算。
      • divide 方法中使用了异常处理来捕获除零错误。

    • log_activity 装饰器:用于捕获和记录函数执行中的异常。

      • wrapper 函数在调用被装饰的函数时,捕获并打印任何异常。

    • main 函数:程序的入口,包含了异常处理的综合示例。

      • 捕获用户输入的数字转换错误(ValueError)。
      • 根据用户选择的操作符执行相应的计算,并处理无效操作符。
      • 使用try, except, finally块处理文件写入操作中的异常。


  • 执行结果:
在执行过程中,如果发生异常,程序能够捕获并处理这些异常,确保程序不会崩溃并输出适当的错误信息。
Y 推荐文献


  • [Python] Python 异常FAQ - 博客园/千千寰宇
X 参考文献


  • 基础 | 彻底搞懂Python异常处理:try-except-else-finally - 知乎
  • Python异常处理:异常的捕获和处理(try, except, finally)① - CSDN
    本文作者:        千千寰宇   
    本文链接:         https://www.cnblogs.com/johnnyzen   
    关于博文:评论和私信会在第一时间回复,或直接私信我。   
    版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA     许可协议。转载请注明出处!
    日常交流:大数据与软件开发-QQ交流群: 774386015        【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!   

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册