Python-错误和异常处理

本文介绍了Python中的错误和异常处理,包括语法错误和异常的类型。重点讲述了Python的异常处理结构,如捕获所有异常、捕获指定异常、捕获万能异常以及自定义异常。还探讨了如何使用traceback模块来查看更详细的异常信息。

Python的错误主要分为两类:语法错误 和 异常

错误

语法错误错误又称解析错误,是学习 Python 时最常见的错误

举个🌰:

在这里插入图片描述

执行结果如下:

  File "F:\Project\i-python-study\exceptionStudy.py", line 8
    while True
              ^
SyntaxError: invalid syntax
  • 可以看到使用Pycharm时,会自动标注语法有错误
  • 从执行结果也可以看到会报错:SyntaxError: invalid syntax

异常

参考链接:https://www.cnblogs.com/hls-code/p/14865380.html

  • 官方解释:即使语句或表达式使用了正确的语法,执行时仍可能触发错误。执行时检测到的错误称为 异常
  • 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行
  • 异常模块分为两种:
    • 标准异常
    • 自定义异常

标准异常

  • Python的异常处理能力是很强大的,它有很多内置异常,可向用户准确反馈出错信息
  • 在Python中,异常也是对象,可对它进行操作
  • BaseException是所有内置异常的基类,但用户定义的类并不直接继承BaseException
  • 所有的异常类都是从Exception继承,且都在exceptions模块中定义
  • Python自动将所有异常名称放在内建命名空间中,所以程序不必导入exceptions模块即可使用异常。一旦引发而且没有捕捉SystemExit异常,程序执行就会终止
标准异常的层次结构如下:
BaseException  # 所有异常的基类
 +-- SystemExit  # 解释器请求退出
 +-- KeyboardInterrupt  # 用户中断执行(通常是输入^C)
 +-- GeneratorExit  # 生成器(generator)发生异常来通知退出
 +-- Exception  # 常规异常的基类
      +-- StopIteration  # 迭代器没有更多的值
      +-- StopAsyncIteration  # 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
      +-- ArithmeticError  # 各种算术错误引发的内置异常的基类
      |    +-- FloatingPointError  # 浮点计算错误
      |    +-- OverflowError  # 数值运算结果太大无法表示
      |    +-- ZeroDivisionError  # 除(或取模)零 (所有数据类型)
      +-- AssertionError  # 当assert语句失败时引发
      +-- AttributeError  # 属性引用或赋值失败
      +-- BufferError  # 无法执行与缓冲区相关的操作时引发
      +-- EOFError  # 当input()函数在没有读取任何数据的情况下达到文件结束条件(EOF)时引发
      +-- ImportError  # 导入模块/对象失败
      |    +-- ModuleNotFoundError  # 无法找到模块或在在sys.modules中找到None
      +-- LookupError  # 映射或序列上使用的键或索引无效时引发的异常的基类
      |    +-- IndexError  # 序列中没有此索引(index)
      |    +-- KeyError  # 映射中没有这个键
      +-- MemoryError  # 内存溢出错误(对于Python 解释器不是致命的)
      +-- NameError  # 未声明/初始化对象 (没有属性)
      |    +-- UnboundLocalError  # 访问未初始化的本地变量
      +-- OSError  # 操作系统错误,EnvironmentError,IOError,WindowsError,socket.error,select.error和mmap.error已合并到OSError中,构造函数可能返回子类
      |    +-- BlockingIOError  # 操作将阻塞对象(e.g. socket)设置为非阻塞操作
      |    +-- ChildProcessError  # 在子进程上的操作失败
      |    +-- ConnectionError  # 与连接相关的异常的基类
      |    |    +-- BrokenPipeError  # 另一端关闭时尝试写入管道或试图在已关闭写入的套接字上写入
      |    |    +-- ConnectionAbortedError  # 连接尝试被对等方中止
      |    |    +-- ConnectionRefusedError  # 连接尝试被对等方拒绝
      |    |    +-- ConnectionResetError    # 连接由对等方重置
      |    +-- FileExistsError  # 创建已存在的文件或目录
      |    +-- FileNotFoundError  # 请求不存在的文件或目录
      |    +-- InterruptedError  # 系统调用被输入信号中断
      |    +-- IsADirectoryError  # 在目录上请求文件操作(例如 os.remove())
      |    +-- NotADirectoryError  # 在不是目录的事物上请求目录操作(例如 os.listdir())
      |    +-- PermissionError  # 尝试在没有足够访问权限的情况下运行操作
      |    +-- ProcessLookupError  # 给定进程不存在
      |    +-- TimeoutError  # 系统函数在系统级别超时
      +-- ReferenceError  # weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象
      +-- RuntimeError  # 在检测到不属于任何其他类别的错误时触发
      |    +-- NotImplementedError  # 在用户定义的基类中,抽象方法要求派生类重写该方法或者正在开发的类指示仍然需要添加实际实现
      |    +-- RecursionError  # 解释器检测到超出最大递归深度
      +-- SyntaxError  # Python 语法错误
      |    +-- IndentationError  # 缩进错误
      |         +-- TabError  # Tab和空格混用
      +-- SystemError  # 解释器发现内部错误
      +-- TypeError  # 操作或函数应用于不适当类型的对象
      +-- ValueError  # 操作或函数接收到具有正确类型但值不合适的参数
      |    +-- UnicodeError  # 发生与Unicode相关的编码或解码错误
      |         +-- UnicodeDecodeError  # Unicode解码错误
      |         +-- UnicodeEncodeError  # Unicode编码错误
      |         +-- UnicodeTranslateError  # Unicode转码错误
      +-- Warning  # 警告的基类
           +-- DeprecationWarning  # 有关已弃用功能的警告的基类
           +-- PendingDeprecationWarning  # 有关不推荐使用功能的警告的基类
           +-- RuntimeWarning  # 有关可疑的运行时行为的警告的基类
           +-- SyntaxWarning  # 关于可疑语法警告的基类
           +-- UserWarning  # 用户代码生成警告的基类
           +-- FutureWarning  # 有关已弃用功能的警告的基类
           +-- ImportWarning  # 关于模块导入时可能出错的警告的基类
           +-- UnicodeWarning  # 与Unicode相关的警告的基类
           +-- BytesWarning  # 与bytes和bytearray相关的警告的基类
           +-- ResourceWarning  # 与资源使用相关的警告的基类。被默认警告过滤器忽略。

捕获异常

  • 当发生异常时,我们就需要对异常进行捕获,然后进行相应的处理
  • python的异常捕获常用try…except…结构,把可能发生错误的语句放在try模块里,用except来处理异常,每一个try,都必须至少对应一个except
python异常相关的关键字
关键字说明
try/except捕获异常并处理
pass忽略异常
as定义异常实例(except MyError as e)
else如果try中的语句没有引发异常,则执行else中的语句
finally无论是否出现异常,finally内的代码都会执行
raise抛出/引发异常
捕获所有异常
try:
    1 / 0
except:
    print("所有异常")
捕获指定异常
try:
    1 / 0
except ZeroDivisionError:
    print("ZeroDivisionError异常")
捕获万能异常
try:
    1 / 0
except Exception:
    print("万能异常")
    
try:
    f = open("file-not-exists", "r")
except IOError as e:
    print("open exception: %s: %s" % (e.errno, e.strerror))
捕获多个异常

捕获多个异常 不区分 优先级

try:
    f = open("file-not-exists", "r")
except (IOError,ZeroDivisionError):
    print("多个异常:IOError,ZeroDivisionError")
# 
try:
    f = open("file-not-exists", "r")
except (IOError, ZeroDivisionError) as e:
    print("多个异常:IOError,ZeroDivisionError:", e)

捕获多个异常 区分 优先级

try:
    1 / 0
except ZeroDivisionError as ze:
    print('ZeroDivisionErro异常:', ze)
except IOError as ioe:
    print('IOError异常:', ioe)
except AssertionError as ae:
    print('AssertionError异常:', ae)
注意:
  • 捕获多个异常区分优先级时,执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句
  • 如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句
  • 如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制
  • 如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中
异常中的else

使用场景:如果判断完没有某些异常之后还想做其他事,就可以使用else语句,代码如下

# 用法1(推荐)
try:
    1 / 2
except ZeroDivisionError as ze:
    print('ZeroDivisionErro异常:', ze)
except IOError as ioe:
    print('IOError异常:', ioe)
else:
    print("干点其他事,emmm")
# 用法2 
try:
    1 / 2
except ZeroDivisionError:
    print('ZeroDivisionErro异常:')
else:
    print("干点其他事,emmm")
异常中的finally

try…finally…语句无论是否发生异常,都将会执行finally里的代码

# 未触发异常
try:
    1 / 2
except ZeroDivisionError:
    print('ZeroDivisionErro异常:')
else:
    print("干点其他事,emmm")
finally:
    print("finally必须执行")
# 触发异常
try:
    1 / 0
except ZeroDivisionError:
    print('ZeroDivisionErro异常:')
else:
    print("干点其他事,emmm")
finally:
    print("finally必须执行")

执行结果如下:
在这里插入图片描述

补充
  • finally的作用:一般写清理关闭操作,如:关闭文件、关闭数据库连接等等
  • 若没有 break 、 continue 、 return 、异常,执行顺序是:try - else - finally
raise主动触发异常
  • 语法:raise [Exception [, args [, traceback]]]
# 主动触发万能异常
if 1 == 1:
    raise Exception("主动抛出的异常")
# 主动触发指定异常
if 1 == 1:
    raise ValueError("主动抛出的ValueError")

使用traceback模块查看异常

官方文档部分:https://docs.python.org/2/library/traceback.html

不使用traceback的异常信息
try:
    1/0
except Exception as e:
    print(e)

执行结果如下:
在这里插入图片描述

使用traceback的异常信息
try:
    1 / 0
except Exception as e:
    traceback.print_exc()

执行结果如下:
在这里插入图片描述

可以看到打印了详细错误信息

拓展:traceback.print_exc()跟traceback.format_exc()有什么区别呢?
  • format_exc()返回字符串,并且不会直接打印出来
  • print_exc()则直接给打印出来
  • 即traceback.print_exc()等于print(traceback.format_exc())
  • print_exc()还可以接受file参数直接写入到一个文件:traceback.print_exc(file=open('tb.txt','w+'))

自定义异常

此外,你也可以通过创建一个新的异常类拥有自己的异常,异常应该是通过直接或间接的方式继承自Exception类。下面创建了一个MyError类,基类为Exception,用于在异常触发时输出更多的信息

class NewException(Exception):
    def __init__(self,errorinfo):
        super().__init__(self)
        self.errorinfo = errorinfo
    def __str__(self):
        return self.errorinfo
    
def factorial(num):
    try:
        if num < 0 or type(num) != int:
            raise NewException("我说你错了,你就是错了")
    	else:
            return num * factorial(num-1)
    except Exception as e:
        print(e)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值