logo

Pyhton 异常处理

王哲峰 / 2022-07-26


目录

为什么使用异常?

异常处理器会留下标识, 并可执行一些代码. 程序前进到某处代码时, 产生异常, 因而会使 Python 立即跳到那个标识, 而放弃留下该标识之后所调用的任何激活的函数. 这个协议提供了一种固有的方式响应不寻常的事件. 再者, 因为 Python 会立即跳到处理器的语句代码更简单——对于可能会发生失败的函数的每次调用, 通常就没有必要检查这些函数的状态码.

异常由四个语句处理:

异常的角色

在 Python 中, 异常通常可以用于各种用途, 下面是它最常见的几种角色:

默认异常处理器

默认的异常处理器: 就是打印标准出错消息. 消息包括引发的异常还有堆栈跟踪, 也就是异常发生时激活的程序行和函数清单.

通过交互模式编写代码时, 文件名就是 “stdin” (标准输入流), 表示标准的输入流. 当在 IDLE GUI 的交互 shell 中工作的时候, 文件名就是 “pyshell”, 并且会显示出源行.

在交互模式提示符环境外启动的更为现实的程序中, 顶层的默认处理器也会立刻终止程序. 对简单的脚本而言, 这种行为很有道理. 错误通常应该是致命错误, 而当其发生时, 所能做的就是 查看标准出错消息.

捕获异常

如果不想要默认的异常行为, 就需要把调用包装在 try 语句内, 自行捕捉异常. 当 try 代码块执行时触发异常, Python 会自动跳至处理器(指出引发的异常名称的 except 分句下面的代码块), 并会从中恢复执行.

引发异常

用户定义的异常

终止行为

异常层次结构

内置异常的类层级结构如下:

BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
    +-- StopIteration
    +-- StopAsyncIteration
    +-- ArithmeticError
    |    +-- FloatingPointError
    |    +-- OverflowError
    |    +-- ZeroDivisionError
    +-- AssertionError
    +-- AttributeError
    +-- BufferError
    +-- EOFError
    +-- ImportError
    |    +-- ModuleNotFoundError
    +-- LookupError
    |    +-- IndexError: 序列检测到超出边界的索引运算
    |    +-- KeyError
    +-- MemoryError
    +-- NameError
    |    +-- UnboundLocalError
    +-- OSError
    |    +-- BlockingIOError
    |    +-- ChildProcessError
    |    +-- ConnectionError
    |    |    +-- BrokenPipeError
    |    |    +-- ConnectionAbortedError
    |    |    +-- ConnectionRefusedError
    |    |    +-- ConnectionResetError
    |    +-- FileExistsError
    |    +-- FileNotFoundError
    |    +-- InterruptedError
    |    +-- IsADirectoryError
    |    +-- NotADirectoryError
    |    +-- PermissionError
    |    +-- ProcessLookupError
    |    +-- TimeoutError
    +-- ReferenceError
    +-- RuntimeError
    |    +-- NotImplementedError
    |    +-- RecursionError
    +-- SyntaxError
    |    +-- IndentationError
    |         +-- TabError
    +-- SystemError
    +-- TypeError
    +-- ValueError
    |    +-- UnicodeError
    |         +-- UnicodeDecodeError
    |         +-- UnicodeEncodeError
    |         +-- UnicodeTranslateError
    +-- Warning
        +-- DeprecationWarning
        +-- PendingDeprecationWarning
        +-- RuntimeWarning
        +-- SyntaxWarning
        +-- UserWarning
        +-- FutureWarning
        +-- ImportWarning
        +-- UnicodeWarning
        +-- BytesWarning
        +-- ResourceWarning

语法错误(Syntax Errors)

def action():
    pass

try:
    action()
except:
    print('something')
except NameError:
    print('statements')
except IndexError as data:
    print('statements')
except KeyError, value2:
    print('statements')
except (AttributeError, TypeError):
    print('statements')
except (AttributeError, TypeError, SyntaxError), value3:
    print('statements')
else:
    print('statements')
finally:
    print('statements')

捕获异常

捕获所有异常

def action():
    pass

try:
    action()
except Exception as e:
    print("Reason:", e)

创建自定义异常

# 创建新的异常类
class Error_1(Exception):
    pass

class Error_2(Error_1):
    pass

class Error_3(Error_2):
    pass

# 使用自定义的异常
try:
    action()
except Error_1 as e:
    print("Reason:", e)
except Error_2 as e:
    print("Reason:", e)
except Error_3 as e:
    print("Reason:", e)

traceback

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import traceback as traceback

print(sys.exc_info())
print(sys.exc_info()[2])

try:
    a = 1 / 0
except ZeroDivisionError:
    print(sys.exc_info())
    print(sys.exc_info()[2])
    tb.print_exc(file = sys.stdout)