python有许多内置异常。比如我们常见的TypeError, AttributeError, ValueError等等。 实际上所有的异常都源自一个基类BaseException。 注意并不是Exception类。我们一般在异常处理时捕获的称之为Concrete exceptions,用Exception可以捕获所有这些 Concrete exceptions。
各种异常并不是毫无关系的,有些异常是有继承关系的。 比如ModuleNotFoundError是ImportError的子类。 except子句中使用ImportError可以同时捕获ImportError和MoudleNotFoundError这两种异常。
但像Syntax Error这种异常是语法错误,python解释器会立即抛出,根本不会运行到我们的try … catch语句里。
下面的示例是一个语法错误
while True print('Hello world')
File "<stdin>", line 1
while True print('Hello world')
^^^^^
SyntaxError: invalid syntax
try … except 语句进行异常捕获和处理。
try:
x = int('abc')
except ValueError:
print("Oops! That was no valid number. Try again...")
但如果except里没对捕获到的异常类型做处理,只异常会继续抛出。
try:
x = int('abc')
except NameError:
print("处理一个NameError")
运行结果:
Traceback (most recent call last):
File "F:\RolandWork\PythonProjects\studyPython\forTest.py", line 2, in <module>
x = int('abc')
^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'abc'
except子句可以捕获多种异常。Exception代表所有类型异常。 要想引用异常,使用as语句,将异常实例存储到变量中。
try:
x = int('abc')
except NameError:
print("处理一个NameError")
except AttributeError:
print("处理一个ValueError")
except Exception as e:
print(f"处理一个{type(e)}")
输出结果:
处理一个<class 'ValueError'>
还可以用元组来同时处理多种异常。
try:
x = int('abc')
except (NameError, AttributeError, ValueError) as e:
print(f"处理一个{type(e)}")
输出结果:
处理一个<class 'ValueError'>
有些异常之间存在继承关系,比如except子句使用ImportError可以捕获ModuleNotFoundError:
try:
print('do something before error')
raise ModuleNotFoundError
except ImportError as e:
print(f'got ImportError: {type(e)}')
输出结果:
do something before error
got ImportError: <class 'ModuleNotFoundError'>
下面演示一下自定义异常,及其继承关系的用法。
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
输出结果:
B
C
D
异常的except子句里的顺序也重要,一般我们会先处理具体的异常,然后处理一般的异常。因为一旦走到一个异常类型分支,就不会再处理后面的except子句。
比如我们将上面的例子中的except子句的顺序做下调整,将B放在上面,由于B是C和D的基类,所以异常都在except B这里处理了,不会执行后面的except子句。
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except B:
print("B")
except D:
print("D")
except C:
print("C")
输出结果如下:
B
B
B
当我们使用raise加一个Error类时,其实python会自动将其实例化成一个异常实例。 即raise ModuleNotFoundError 等价于 raise ModuleNotFoundError(),并且通常异常类型都至少有一个参数用来实例化异常消息。
try:
print('do something before error')
raise ModuleNotFoundError("some module not found")
except ImportError as e:
print(f'got ImportError: {e}')
输出结果:
do something before error
got ImportError: some module not found
其实在异常内部有个args属性,里面存储了异常的信息。比如我们主动抛出的异常时加的描述性信息。具体到不同的异常时,args属性数量可能不同。python的内置异常都在其__str__方法里帮我们实现了对args属性里内容的输出,所以我们直接print(e)时就能看到这些属性内容。
try:
raise Exception('spam', 'eggs')
except Exception as inst:
print(type(inst)) # the exception type
print(inst.args) # arguments stored in .args
print(inst) # __str__ allows args to be printed directly,
# but may be overridden in exception subclasses
x, y = inst.args # unpack args
print('x =', x)
print('y =', y)
输出结果:
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
来源链接:https://www.cnblogs.com/rolandhe/p/18685710










没有回复内容