Python异常
异常定义
- 即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误。
- 运行期检测到的错误被称为异常。
- 默认情况下,异常不会被程序处理,以错误信息的形式报出。
- 回溯信息
当程序运行时,发生了未处理的异常,Python就将终止执行程序,并以堆栈回溯(Traceback,也 称向后追踪)的形式显示异常发生的上下文。
异常继承关系
- BaseException是所有异常的基类。
- 常规异常的基类是Exception。
BaseException # 所有异常的基类
+-- SystemExit # 解释器请求退出
+-- KeyboardInterrupt 用户中断执行(通常是输入^C)
+-- GeneratorExit # 生成器(generator)发生异常来通知退出
+-- Exception # 常规异常的基类
+-- StopIteration # 迭代器没有更多的值
+-- StandardError # 标准错误
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
| +-- ImportError
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| +-- MemoryError
| +-- NameError
| | +-- UnboundLocalError
| +-- ReferenceError
| +-- RuntimeError
| | +-- NotImplementedError
| +-- SyntaxError
| | +-- IndentationError
| | +-- TabError
| +-- SystemError
| +-- TypeError
| +-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarnin
+-- ImportWarnin
+-- UnicodeWarnin
+-- BytesWarning
回溯信息
- 回溯信息告诉我们应该去哪里寻找问题的根源,对解决问题非常有帮助。
'2' + 2 # int 不能与 str 相加,触发异常
result:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
常见异常
名称 | 描述 | 举例 |
---|---|---|
AssertionError | 断言语句失败(assert 后的条件为假) | assert False, ‘错了吧’ ==> AssertionError: 错了吧 |
AttributeError | 访问的对象属性不存在 | “abc”.append() ==> AttributeError: ‘str’ object has no attribute ‘append’ |
IndexError | 下标索引超出序列范围 | “abc”[4] ==> IndexError: string index out of range |
NameError | 访问一个未声明的变量 | del a; print(a) ==> NameError: name ‘a’ is not defined |
IndentationError | 代码没有正确对齐,主要是缩进错误 | |
IOError | 输入/输出异常,主要是无法打开文件 | |
KeyError | 访问字典里不存在的键 | {“a”:1,“b”:2}[“c”] ==> KeyError: ‘c’ |
SyntaxError | python语法错误 | |
TypeError | 不同类型数据之间的无效操作(传入对象类型与要求的不符合 | [1,2,3]+5 ==> TypeError: can only concatenate list (not “int”) to list |
ValueError | 传入无效的值,即使值的类型是正确的 | |
ZeroDivisionError | 除法运算中除数0 或者 取模运算中模数为0 |
异常处理
在代码被解释执行的过程中可能会抛出异常。对于这么不可预测的异常状态如何处理?
- 即使程序出错,也不想让程序终止。
- 如果出错了,需要特殊处理。
- 需要使用异常处理语句。
- try后的语句为捕获异常部分。
- except后的为异常处理部分。
try except else finally
- try结构必须要有。
- except结构必须要有。
- else结构可有可无。
- finally结构可有可无。
- 如果try之后或者except之后有return,但是有finally,最后会返回finally的return值。
语法结构
try:
执行的语句(可能有异常)
except [异常类型1] [as err1]: # 异常类型可有可无 as e可有可无
该指定类型异常下执行的语句
except [异常类型2] [as err1]:
该指定类型异常下执行的语句
except (异常类型1,异常类型2,...):
多种异常中的任何一个异常发生会执行的语句
except: # 其它异常
...
else:
无异常时执行的语句
finally: # 可有可无
有无异常都会执行的语句
except 语法结构
except:
- 所有前面捕获的异常都将进入excpet的异常执处理。
except [异常类型]
- 指定名称的异常被捕获后才进入excpet的异常执处理。
except [异常类型] as err(可以随意指定名称)
- 可以使用指定变量名访问异常类型的一些信息。
- 如err.__class__.__name__为异常名称,err为描述信息。
except Exception as err:
- 所有常规的Exception基类的异常都会进入excpet的异常执处理。
except (异常类型1,异常类型2,…)
- 指定的多种异常组合。
else
- 无异常时执行else语句。
finally
- 无论有无异常,都会执行的语句。
- 如果有finally语句中有return语句,finally中的return语句就是最终的返回值。
异常举例
a = "3"; b = 5
try:
c = a + 5
d = b / 0
except TypeError as err1:
print("TypeError", err1.__class__.__name__)
except ZeroDivisionError as err2:
print("ZeroDivisionError", err2)
finally:
print("finally")
result:
TypeError TypeError
finally
a = 3
try:
b = a / 0
except Exception as err:
print("错误类型:", err.__class__.__name__, err)
finally:
print("finally")
result:
错误类型: ZeroDivisionError division by zero
finally
a = 5
try:
b = a + 5
print(b)
except TypeError as err1:
print("TypeError", err1.__class__.__name__)
else:
print("no error")
finally:
print("finally")
result:
10
no error
finally
抛出异常
- 当程序执行不符合自己的设计目标时,可以主动抛出异常。
- 使用raise exception(“提示信息”),当扔了以后,会被except接收。
raise语法结构
# exceptionName:异常的种类,当不确定时,使用Exception
# reason:对异常的描述
raise [exceptionName [(reason)]]
- 单独一个 raise。该语句引发当前上下文中捕获的异常(比如在 except 块中),或默认引发 RuntimeError 异常。
- raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常。
- raise 异常类名称(描述信息):在引发指定类型的异常的同时,附带异常的描述信息。
raise
result: RuntimeError: No active exception to reraise
raise Exception("除数不能为零")
result: Exception: 除数不能为零
raise ZeroDivisionError("除数不能为零")
result: ZeroDivisionError: 除数不能为零
用户自定义异常
- 通过创建一个新的异常类来拥有自己的异常。
- 异常类继承自Exception 类,可以直接继承,或者间接继承。
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr("description")
try:
raise MyError(4)
except MyError as err:
print("My exception occurred,", err, err.value)
result:
My exception occurred, 'description' 4
assert
- 使用assert可以在出现有异常的代码处直接终止运行。 而不用等到程序执行完毕之后抛出异常。
- 判断expression, 如果为False,则raise出一个异常AssertionError
assert expression [, arguments]等价于
if not expression:
raise AssertionError(arguments)
assert 1==2, '1 不等于 2'
result:
AssertionError: 1 不等于 2