介绍
在这个实验中,你将学习如何在 Python 中检查异常是否属于特定类型,这是进行有效错误处理的一项关键技能。本实验重点在于理解异常层次结构,并利用这些知识来识别特定的异常类型。
本实验将引导你探索 Python 异常层次结构,从基类 BaseException 及其子类(如 Exception)开始。你将创建一个 Python 脚本 exception_hierarchy.py 来打印异常层次结构,这样你就能直观地看到不同异常类之间的关系。随后,你将运用这些知识,在后续步骤中使用 isinstance() 和直接类比较来检查异常类型。
理解异常层次结构
在这一步中,你将学习 Python 中的异常层次结构。理解这个层次结构对于有效的错误处理至关重要。Python 中的异常以树状结构组织,顶部是基类,更具体的异常类从它继承而来。
所有异常的基类是 BaseException。直接从 BaseException 继承的有 Exception、GeneratorExit、KeyboardInterrupt 和 SystemExit。Exception 类是大多数内置异常的超类,这些异常表示你的程序可能遇到的错误。
让我们创建一个 Python 脚本来探索这个层次结构。
打开你的 VS Code 编辑器。
在
~/project目录下创建一个名为exception_hierarchy.py的新文件。~/project/exception_hierarchy.py在
exception_hierarchy.py文件中添加以下代码:def print_exception_hierarchy(exception_class, indent=0): """Prints the exception hierarchy starting from a given exception class.""" print(' ' * indent + str(exception_class)) for subclass in exception_class.__subclasses__(): print_exception_hierarchy(subclass, indent + 1) print("Exception Hierarchy:") print_exception_hierarchy(Exception)这个脚本定义了一个递归函数
print_exception_hierarchy,它从Exception类开始打印异常层次结构。在终端中使用以下命令运行脚本:
python exception_hierarchy.py这将在终端中打印出异常层次结构的树状结构。
示例输出:
Exception Hierarchy: <class 'Exception'> <class 'ArithmeticError'> <class 'FloatingPointError'> <class 'OverflowError'> <class 'ZeroDivisionError'> <class 'decimal.DivisionByZero'> <class 'AssertionError'> <class 'AttributeError'> <class 'BufferError'> <class 'EOFError'> <class 'ImportError'> <class 'ModuleNotFoundError'> <class 'ZipImportError'> <class 'LookupError'> <class 'IndexError'> <class 'KeyError'> <class 'tracemalloc.DomainKey'> <class 'MemoryError'> <class 'NameError'> <class 'UnboundLocalError'> <class 'OSError'> <class 'BlockingIOError'> <class 'ChildProcessError'> <class 'ConnectionError'> <class 'BrokenPipeError'> <class 'ConnectionAbortedError'> <class 'ConnectionRefusedError'> <class 'ConnectionResetError'> <class 'FileExistsError'> <class 'FileNotFoundError'> <class 'InterruptedError'> <class 'InterruptedSystemCall'> <class 'IsADirectoryError'> <class 'NotADirectoryError'> <class 'PermissionError'> <class 'ProcessLookupError'> <class 'TimeoutError'> <class 'UnsupportedOperation'> <class 'itertools.Incomplete'> <class 'signal.ItimerError'> <class 'ReferenceError'> <class 'RuntimeError'> <class 'NotImplementedError'> <class 'asyncio.exceptions.IncompleteReadError'> <class 'zlib.error'> <class '_frozen_importlib._DeadlockError'> <class 'RecursionError'> <class 'StopAsyncIteration'> <class 'StopIteration'> <class 'SyntaxError'> <class 'IndentationError'> <class 'TabError'> <class 'SystemError'> <class 'TypeError'> <class 'ValueError'> <class 'UnicodeError'> <class 'UnicodeDecodeError'> <class 'UnicodeEncodeError'> <class 'UnicodeTranslateError'> <class 'Warning'> <class 'BytesWarning'> <class 'DeprecationWarning'> <class 'EncodingWarning'> <class 'FutureWarning'> <class 'ImportWarning'> <class 'PendingDeprecationWarning'> <class 'ResourceWarning'> <class 'RuntimeWarning'> <class 'SyntaxWarning'> <class 'UnicodeWarning'> <class 'UserWarning'>这个输出展示了异常的层次结构,以
Exception作为基类,各种子类代表特定类型的错误。理解这个层次结构有助于你在适当的粒度级别捕获异常。例如,你可以捕获像ZeroDivisionError这样的特定异常,或者像ArithmeticError(它是ZeroDivisionError的父类)这样更通用的异常。
对异常使用 isinstance() 函数
在这一步中,你将学习如何使用 isinstance() 函数来检查一个异常是否是某个特定类或类元组的实例。这对于灵活处理不同类型的异常很有用。
isinstance() 函数接受两个参数:一个对象和一个类信息(classinfo)。如果对象是类信息所指定类的实例,或者是该类的子类的实例,函数将返回 True;否则返回 False。
让我们创建一个 Python 脚本来演示如何对异常使用 isinstance() 函数。
打开你的 VS Code 编辑器。
在
~/project目录下创建一个名为isinstance_exception.py的新文件。~/project/isinstance_exception.py在
isinstance_exception.py文件中添加以下代码:try: result = 10 / 0 except Exception as e: if isinstance(e, ZeroDivisionError): print("Caught a ZeroDivisionError!") elif isinstance(e, ArithmeticError): print("Caught an ArithmeticError!") else: print("Caught some other exception!") print("Program continues...")在这个脚本中,我们尝试将 10 除以 0,这将引发一个
ZeroDivisionError异常。然后我们捕获该异常,并使用isinstance()函数检查它是否是ZeroDivisionError或ArithmeticError的实例。在终端中使用以下命令运行脚本:
python isinstance_exception.py这将在终端中打印出 "Caught a ZeroDivisionError!"。
示例输出:
Caught a ZeroDivisionError! Program continues...输出结果表明,
isinstance()函数正确地识别出该异常是ZeroDivisionError的实例。由于ZeroDivisionError是ArithmeticError的子类,第一个if条件满足,因此打印出相应的消息。现在,让我们修改脚本以捕获更通用的异常。
将
isinstance_exception.py文件修改为以下内容:try: result = int("abc") except Exception as e: if isinstance(e, ZeroDivisionError): print("Caught a ZeroDivisionError!") elif isinstance(e, ValueError): print("Caught a ValueError!") elif isinstance(e, ArithmeticError): print("Caught an ArithmeticError!") else: print("Caught some other exception!") print("Program continues...")在这个修改后的脚本中,我们尝试将字符串 "abc" 转换为整数,这将引发一个
ValueError异常。再次使用相同的命令运行脚本:
python isinstance_exception.py这将在终端中打印出 "Caught a ValueError!"。
示例输出:
Caught a ValueError! Program continues...这个输出表明,
isinstance()函数可用于区分不同类型的异常,并相应地处理它们。
使用异常类进行检查
在这一步中,你将学习如何在 except 块中直接检查特定的异常类。与使用 isinstance() 相比,这是一种更直接且通常更清晰的异常处理方式。
当你使用 except ExceptionType as e: 时,你是在告诉 Python 仅捕获类型为 ExceptionType 或其子类的异常。
让我们创建一个 Python 脚本来演示这一点。
打开你的 VS Code 编辑器。
在
~/project目录下创建一个名为exception_classes.py的新文件。~/project/exception_classes.py在
exception_classes.py文件中添加以下代码:try: result = 10 / 0 except ZeroDivisionError as e: print("Caught a ZeroDivisionError:", e) except ArithmeticError as e: print("Caught an ArithmeticError:", e) except Exception as e: print("Caught some other exception:", e) print("Program continues...")在这个脚本中,我们尝试将 10 除以 0,这将引发一个
ZeroDivisionError异常。我们有三个except块:一个用于ZeroDivisionError,一个用于ArithmeticError,还有一个用于Exception。在终端中使用以下命令运行脚本:
python exception_classes.py这将在终端中打印出 "Caught a ZeroDivisionError: division by zero"。
示例输出:
Caught a ZeroDivisionError: division by zero Program continues...输出结果表明,
ZeroDivisionError被第一个except块捕获。现在,让我们修改脚本以引发不同的异常。
将
exception_classes.py文件修改为以下内容:try: result = int("abc") except ZeroDivisionError as e: print("Caught a ZeroDivisionError:", e) except ValueError as e: print("Caught a ValueError:", e) except ArithmeticError as e: print("Caught an ArithmeticError:", e) except Exception as e: print("Caught some other exception:", e) print("Program continues...")在这个修改后的脚本中,我们尝试将字符串 "abc" 转换为整数,这将引发一个
ValueError异常。再次使用相同的命令运行脚本:
python exception_classes.py这将在终端中打印出 "Caught a ValueError: invalid literal for int() with base 10: 'abc'"。
示例输出:
Caught a ValueError: invalid literal for int() with base 10: 'abc' Program continues...这个输出表明,
ValueError被第二个except块捕获。通过在
except块中直接指定异常类,你可以清晰、有条理地处理不同类型的异常。对于简单的异常处理,这种方法通常比使用isinstance()更受青睐。
总结
在本次实验中,你探索了 Python 中的异常层次结构,这对于有效的错误处理至关重要。你了解到,异常以树状结构组织,其中 BaseException 是基类,而 Exception 是大多数内置异常的超类。
你创建了一个 Python 脚本 exception_hierarchy.py,用于打印从 Exception 类开始的异常层次结构。通过运行该脚本,你观察到了异常的树状结构及其相互关系,从而更好地理解了 Python 中异常的组织方式。



