# 异常和错误 ## 语法错误 python 解释器的语法检测不通过,必须在程序执行前就改正。 ```python #语法错误示范一 if #语法错误示范二 def test: pass #语法错误示范三 print(haha ``` ## 逻辑错误 ```python #用户输入不完整(比如输入为空)或者输入非法(输入不是数字) num=input(">>: ") res1 = int(num) #无法完成计算 res1=1/0 res2=1+'str' ``` ## 异常 异常就是程序运行时发生错误的信号,然后程序异常退出。 ![img](异常处理/程序异常.png) ## 异常种类 在 python 中不同的异常可以用不同的类型(类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误。 ```python # 触发IndexError l=['eagle','aa'] l[3] # 触发KeyError dic={'name':'eagle'} dic['age'] # 触发ValueError s='hello' int(s) ``` **常见异常** | 异常类型 | 说明 | | :---------------- | :----------------------------------------------------------- | | AttributeError | 试图访问一个对象没有的属性,比如 foo.x,但是 foo 没有属性 x | | IOError | 输入/输出异常;基本上是无法打开文件 | | ImportError | 无法引入模块或包;基本上是路径问题或名称错误 | | IndentationError | 语法错误(的子类) ;代码没有正确对齐 | | IndexError | 下标索引超出序列边界,比如当x只有三个元素,却试图访问 x[5] | | KeyError | 试图访问字典里不存在的键 | | KeyboardInterrupt | Ctrl + C 被按下 | | NameError | 使用一个还未被赋予对象的变量 | | SyntaxError | Python 代码非法,代码不能编译 | | TypeError | 传入对象类型与要求的不符合 | | UnboundLocalError | 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 | | ValueError | 传入一个调用者不期望的值,即使值的类型是正确的 | **其他异常** | 异常类型 | 说明 | 常见使用场景 | |:--|:--|:--| | ArithmeticError | 所有数值计算错误的基类 | 数学运算出现异常时的通用捕获 | | AssertionError | 断言语句(assert)失败 | 程序内部的条件检查失败时 | | AttributeError | 尝试访问对象不存在的属性 | 使用未定义的对象属性或方法时 | | BaseException | 所有内置异常的基类 | 通常不直接使用,用于自定义异常继承 | | BufferError | 与缓冲区相关的操作错误 | 在使用缓冲区对象时出现错误 | | BytesWarning | 字节相关的警告 | 字节操作的潜在问题警告 | | DeprecationWarning | 关于使用已弃用功能的警告 | 使用即将被移除的特性时 | | EnvironmentError | 操作系统错误的基类 | 系统相关操作异常的通用捕获 | | EOFError | 到达文件末尾,无法读取 | 文件读取操作遇到意外的EOF | | Exception | 常规错误的基类 | 捕获所有非系统退出的异常 | | FloatingPointError | 浮点计算错误 | 浮点数运算出现特殊情况 | | FutureWarning | 关于未来特性改变的警告 | 代码可能在未来版本不兼容 | | GeneratorExit | 生成器被关闭 | 生成器的 close() 方法被调用 | | ImportError | 导入模块失败 | 模块导入路径错误或模块不存在 | | ImportWarning | 导入模块时的警告 | 模块导入可能存在问题 | | IndentationError | 缩进错误 | Python 代码缩进不正确 | | IndexError | 序列中没有此索引 | 访问列表等序列的越界索引 | | IOError | 输入/输出操作失败 | 文件操作、网络请求等 IO 操作失败 | | KeyboardInterrupt | 用户中断执行 | 程序被 Ctrl+C 中断 | | KeyError | 映射中没有这个键 | 字典中不存在的键访问 | | MemoryError | 内存溢出 | 程序耗尽可用内存 | | NameError | 未声明/初始化对象 | 使用未定义的变量 | | NotImplementedError | 尚未实现的方法 | 抽象基类方法需要子类实现 | | OSError | 操作系统相关的错误 | 文件权限、系统调用等错误 | | OverflowError | 数值运算超出最大限制 | 数值计算结果超出表示范围 | | ReferenceError | 弱引用试图访问已经垃圾回收了的对象 | 使用弱引用时的对象访问 | | RuntimeError | 一般的运行时错误 | 不适合其他类别的运行时错误 | | RuntimeWarning | 可疑的运行时行为警告 | 运行时可能存在的问题警告 | | StopIteration | 迭代器没有更多的值 | 迭代器遍历完成 | | SyntaxError | Python 语法错误 | 代码语法错误,无法编译 | | SyntaxWarning | 可疑的语法警告 | 语法虽然正确但可能存在问题 | | SystemError | 一般的解释器系统错误 | Python 解释器内部错误 | | SystemExit | 解释器请求退出 | 调用 `sys.exit()` 请求退出程序 | | TabError | Tab和空格混用 | 混合使用 Tab 和空格导致的错误 | | TypeError | 对类型无效的操作 | 操作或函数应用于不适当类型 | | UnboundLocalError | 访问未初始化的本地变量 | 在赋值前引用局部变量 | | UnicodeError | Unicode 相关的错误 | Unicode编码/解码错误的基类 | | UnicodeDecodeError | Unicode 解码错误 | 无法将字节解码为 Unicode | | UnicodeEncodeError | Unicode 编码错误 | 无法将 Unicode 编码为字节 | | UnicodeTranslateError | Unicode 转换错误 | Unicode 转换过程中的错误 | | UnicodeWarning | Unicode 相关警告 | Unicode 操作的潜在问题警告 | | UserWarning | 用户代码生成的警告 | 用户自定义的警告信息 | | ValueError | 传入无效的参数 | 值虽然类型正确但不合适 | | Warning | 警告的基类 | 所有警告类型的基类 | | ZeroDivisionError | 除数为零 | 数值除以零或取模零 # 异常处理 - python 解释器检测到错误,触发异常(也允许程序员自己触发异常) - 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关) - 如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理 - 异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前就修正 ```python # 错误写法: num1 = input('>>: ') if num1.isdigit(): int(num1) elif num1.isspace(): print('输入的是空格,就执行我这里的逻辑') elif len(num1) == 0: print('输入的是空,就执行我这里的逻辑') else: print('其他情情况,执行我这里的逻辑') ''' 问题: 1. 使用 if 的方式我们只为第一段代码加上了异常处理,但这些 if,跟你的代码逻辑并无关系,这样你的代码会因为可读性差而不容易被看懂 2. 这只是我们代码中的一个小逻辑,如果类似的逻辑多,那么每一次都需要判断这些内容,就会我们的代码特别冗长。 ''' # 正确写法: try: num = input("<<:") int(num) except: print('你输入的是非数字') finally: print('程序结束') ``` ## 基本语法 ```python try: 被检测的代码块 except 异常类型: try 被检测的代码块,就执行这个位置的逻辑 ... else: 正常执行逻辑 finally: 扫尾工作 ``` ## 常见示例 **示例**:处理迭代器获取时 `StopIteration` 异常 ```python iterator01 = ( i** 2 for i in range(3) ) while True: try: print(iterator01.__next__()) except StopIteration as e: print(e) break ``` **示例**:处理数据类型转换时 `ValueError` 异常 ```python s1 = 'hello' try: int(s1) except ValueError as e: print(e) # Output: invalid literal for int() with base 10: 'hello' ``` **示例**:多分支异常处理 ```python s1 = 'hello' try: int(s1) except IndexError as e: print(e) except KeyError as e: print(e) except ValueError as e: print(e) ``` **Exception** ```python s1 = 'hello' try: int(s1) except Exception as e: print(e) ``` 多分支加万能异常 ```python s1 = 'hello' try: int(s1) except IndexError as e: print(e) except KeyError as e: print(e) except ValueError as e: print(e) except Exception as e: print(e) ``` **其他异常情况** ```python s1 = '10' try: int(s1) except IndexError as e: print(e) except KeyError as e: print(e) except ValueError as e: print(e) except Exception as e: print(e) else: print('try内代码块没有异常则执行我') finally: print('无论异常与否,都会执行该模块,通常是进行清理工作') ``` ## 主动触发异常 ```python try: raise TypeError('类型错误') except Exception as e: print(e) ``` ## 自定义异常 ```python class EvaException(BaseException): def __init__(self,msg): self.msg=msg def __str__(self): return self.msg try: raise EvaException('类型错误') except EvaException as e: print(e) ``` **总结**:代码更健壮,更易组织,更清晰。