【Python笔记】捕获异常

1 Python错误处理机制

一旦出错,还要一级一级上报,直到某个函数可以处理该错误(比如,给用户输出一个错误信息)。

所以高级语言通常都内置了一套 try...except...finally... 的错误处理机制,Python也不例外。

让我们用一个例子来看看 try 的机制:

try:
    print('try...') 
    r = 10 / 0 
    print('result:', r) 
except ZeroDivisionError as e: 
    print('except:', e) 
finally:
    print('finally...') 
    print('END')

try…
except: division by zero
finally…
END

try:
    print('try...') 
    r = 10 / 0 
    print('result:', r) 
except ZeroDivisionError: 
    print('except:', ZeroDivisionError) 
finally:
    print('finally...') 
    print('END')

try…
except: <class ‘ZeroDivisionError’>
finally…
END

当我们认为某些代码可能会出错时,就可以用 try 来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即 except 语句块,执行完 except 后,如果有 finally 语句块,则执行 finally 语句块,至此,执行完毕。

从输出可以看到,当错误发生时,后续语句 print(‘result:’, r) 不会被执行, except 由于捕获到ZeroDivisionError ,因此被执行。最后, finally 语句被执行。然后,程序继续按照流程往下走。如果把除数 0 改成 2 ,则执行结果如下:

try…
result: 5.0
finally…
END

由于没有错误发生,所以 except 语句块不会被执行,但是 finally 如果有,则一定会被执行(可以没有 finally 语句)。

2 不同类型 の 错误

你还可以猜测,错误应该有很多种类,如果发生了不同类型的错误,应该由不同的 except 语句块处理。没错,可以有多个 except 来捕获不同类型的错误:

try:
    print('try...') 
    r = 10 / int('2') 
    print('result:', r) 
except ValueError as e: 
    print('ValueError:', e) 
except ZeroDivisionError as e: 
    print('ZeroDivisionError:', e) 
else:
    print('no error!') 
finally:
    print('finally...') 
    print('END')

try…
result: 5.0
no error!
finally…
END

  • int() 函数可能会抛出 ValueError ,所以我们用一个 except 捕获 ValueError ,用另一个 except捕获 ZeroDivisionError 。
  • 此外,如果没有错误发生,可以在 except 语句块后面加一个 else ,当没有错误发生时,会自动执行else语句

Python的错误其实也是 class ,所有的错误类型都继承自BaseException ,所以在使用 except 时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。比如:

try:
    foo() 
except ValueError as e: 
    print('ValueError') 
except UnicodeError as e: 
    print('UnicodeError')
  • 第二个 except 永远也捕获不到 UnicodeError ,因为UnicodeError 是 ValueError的子类,如果有,也被第一个 except 给捕获了

Python所有的错误都是从 BaseException
类派生的,常见的错误类型和继承关系看这里:https://docs.python.org/3/library/exceptions.html#exception-hierarchy

使用 try…except 捕获错误还有一个巨大的好处,就是可以跨越多层调用,比如函数 main() 调用foo() , foo() 调用 bar() ,结果 bar() 出错了,这时,只要 main() 捕获到了,就可以处理:

def foo(s): 
    return 10 / int(s) 

def bar(s): 
    return foo(s) * 2 

def main(): 
    try:
        bar('0') 
    except Exception as e: 
        print('Error:', e) 
    finally: 
        print('finally...')

也就是说,不需要在每个可能出错的地方去捕获错误,只要在合适的层次去捕获错误就可以了

这样一来,就大大减少了写 try...except...finally 的麻烦

表:Python所有的标准异常类

异常名称 描述
BaseException 所有异常的基类
SystemExit 解释器请求退出
KeyboardInterrupt 用户中断执行(通常是输入^C)
Exception 常规错误的基类
StopIteration 迭代器没有更多的值
GeneratorExit 生成器(generator)发生异常来通知退出
SystemExit Python 解释器请求退出
StandardError 所有的内建标准异常的基类
ArithmeticError 所有数值计算错误的基类
FloatingPointError 浮点计算错误
OverflflowError 数值运算超出最大限制
ZeroDivisionError 除(或取模)零 (所有数据类型)
AssertionError 断言语句失败
AttributeError 对象没有这个属性
EOFError 没有内建输入,到达EOF 标记
EnvironmentError 操作系统错误的基类
IOError 输入/输出操作失败
OSError 操作系统错误
WindowsError 系统调用失败
ImportError 导入模块/对象失败
KeyboardInterrupt 用户中断执行(通常是输入^C)
LookupError 无效数据查询的基类
IndexError 序列中没有没有此索引(index)
KeyError 映射中没有这个键
MemoryError 内存溢出错误(对于Python 解释器不是致命的)
NameError 未声明/初始化对象 (没有属性)
UnboundLocalError 访问未初始化的本地变量
ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError 一般的运行时错误
NotImplementedError 尚未实现的方法
SyntaxError Python 语法错误
IndentationError 缩进错误
TabError Tab 和空格混用
SystemError 一般的解释器系统错误
TypeError 对类型无效的操作
ValueError 传入无效的参数
UnicodeError Unicode 相关的错误
UnicodeDecodeError Unicode 解码时的错误
UnicodeEncodeError Unicode 编码时错误
UnicodeTranslateError Unicode 转换时错误
Warning 警告的基类
DeprecationWarning 关于被弃用的特征的警告
FutureWarning 关于构造将来语义会有改变的警告
OverflflowWarning 旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning 关于特性将会被废弃的警告
RuntimeWarning 可疑的运行时行为(runtime behavior)的警告
SyntaxWarning 可疑的语法的警告
UserWarning 用户代码生成的警告
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值