广告

Python之异常和工具

2018-4-6 18:56 290 0 分类: 软件与OS 文集: Linux笔记
执行open操作?try一下吧!
做缓冲区读取?try一下吧!
操作容器?try一下吧!……
try、try、try,越try越开心,不try不快乐,世界因try而美好。
这里的try就是捕获异常并处理。虽然之前经常使用,但没有系统的学习它。因此俺今天会把这里好好梳理一遍,弄清楚什么是异常,以及异常的处理流程。

先看看异常的完整语法:
try/except: 捕获由Python或你引起的异常并恢复。
try/finally: 无论异常是否发生,执行清理行为。
raise: 手动在代码里触发异常。
assert: 有条件地在代码中触发异常。
with/as: 实现环境管理器。

异常的作用:
异常可以使我们从超级大的代码块中跳出来,跳到异常处理器。可以把异常看作一种结构化的超级goto。异常可以用作错误处理,如果我们读取了一个不存在的变量,没有异常的话,程序会出错并退出,有了异常,我们就可以继续执行以后的代码。异常可以用作事件通知,我们不用判断某段代码的状态值,而只要观察异常即可。异常可以做特殊情况处理,再怎么小心,代码也不可能判断并处理所有的意外,所以扔给异常就行了,没有想到的特殊情况,异常也会处理好。异常能够做终止行为无论实际发生了什么,finally都会保证最后的清理工作正常运行。异常能够做非常规控制流程,Python没有goto语句,我们可以使用异常来实现goto的部分功能。

怎么样?异常是不是非常强大?

示例代码:
x = ['abc',  'def',  'ghi']
print(x[4])
运行结果:
Exception "unhandled IndexError"
list index out of range

这里Python解释器为我们处理了异常。如果我们想自己捕获并处理这个异常:
x = ['abc',  'def',  'ghi']
try:
    print(x[4])
except:
    print('I will continue.')
运行结果:
I will continue.
这样,当我们在一个循环里持续获取x的第四个值时,如果有则打印第四个值,如果没有则继续执行之后的代码,而不是让程序出错并退出。

我们也可以手动引发异常,比如:
x = ['abc',  'def',  'ghi']
try:
    if x[0] == 'abc':
        raise IndexError
except IndexError:
    print('I will continue.')

assert也可以用来引发异常:
x = ['abc',  'def',  'ghi']
try:
    assert x[1] != 'def',  "Index 1 wrong!"
    print('Hello')
except:
    print('I will continue.')
运行结果:
I will continue.
Debug结果:
Exception "AssertionError"
Index 1 wrong!
I will continue.

assert一般用作调试,当它的条件为False的时候,就会触发异常。

定义我们自己的异常:
class NoCoffee(Exception):
    pass
try:
    raise NoCoffee()
except NoCoffee:
    print('No coffee! I cannot work!')
运行结果:
No coffee! I cannot work!

再看看finally的用法:
class NoCoffee(Exception):
    pass
try:
    raise NoCoffee()
except NoCoffee:
    print('No coffee! I cannot work!')
finally:
    print('Not gonna work anyway!')

运行结果:
No coffee! I cannot work!
Not gonna work anyway!

作为一名码农,可以这么任性么?
必须不行啊!老板,俺今天晚上加班,今天晚上加班,今天晚上必须加班!啊哈哈哈!

最后看看with/as:
with open('hello') as file:
    file.write('Hello World')
print('The End')
运行结果:
Exception "unhandled FileNotFoundError"
[Errno 2] No such file or directory: 'hello'

with/as只有在处理某些对象类型时才适用,而且它并不能让用户处理异常后的情形,因此还是try/except/finally更加通用。

结语:
由于Python有异常,所以我们可以不再编写检查错误的代码,无需判断状态位,无需担心罕见的特殊错误,无需那么谨小慎微和神经质。我们假设一切都工作正常,然后集中在业务功能的代码编写。

总之,异常是非常简单的工具,愉快的用起来吧!

----------------------------------------------------------------------------------------
以下是有关异常的、可能不需要了解、但最好了解一下、不了解也不影响、反正了解了有好处的细节。
来看一段完整的代码:
import os
import errno

x = ['abc',  'hello',  '123']
for i in range(4):
    try:
        print(x[i])
        open(x[i])
    except IndexError:
        print('Index wrong')
    except OSError as oe:
        print('error:',  os.strerror(oe.errno))
    except:
        print('Something wrong')
    else:
        print('I am good.')
    finally:
        print('Bye-bye!')
运行结果:
abc
error: No such file or directory
Bye-bye!
hello
error: No such file or directory
Bye-bye!
123
error: No such file or directory
Bye-bye!
Index wrong
Bye-bye!

try里面是我们的业务代码,except可以指定异常名称,如果异常不是指定名称的那种,则会使用没有指定异常的except。如果没有异常发生,则执行else的内容。不论有没有异常发生,都会执行finally中的内容。

广告

文章评论 0条评论)

登录后参与讨论
相关推荐阅读
DiracFatCat 2018-06-19 15:10
【博客大赛】卡尔曼滤波学习笔记(八)可观测性和可控制性 ...
可观测性是指,在给定模型的情况下,动力学系统的状态是否由它的输入输出唯一确定。可观测性是系统模型的特征。如果传感器矩阵H是可逆的,则本系统可观测,因为有:如果传感器矩阵H某些时候是不可逆的,则本系统仍...
DiracFatCat 2018-06-19 10:56
【博客大赛】卡尔曼滤波学习笔记(七)Z变换
如果我们仅仅对离散线性系统感兴趣,那么就使用下面这个表达式:如果u是常量,那么可以写成:为了简化表达式,我们可以将上面写成:离散线性时不变系统的Φ求解,可以使用Z变换。(* 由于本人已经忘记了Z变换的...
DiracFatCat 2018-06-19 10:54
【博客大赛】卡尔曼滤波学习笔记(六)拉普拉斯变换
对于线性时变/时不变系统,求解Φ(t)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
DiracFatCat 2018-06-12 21:11
【博客大赛】卡尔曼滤波学习笔记(五)状态转移矩阵
状态转移矩阵(STMs)是线性微分方程的齐次部分的解。线性微分方程是指:它的齐次部分指:解齐次部分要比解整个方程容易,齐次部分的解可以用来解非齐次部分。Φ(t)被称为齐次方程的基本解,如果它满足下面的...
DiracFatCat 2018-06-09 17:16
【博客大赛】卡尔曼滤波学习笔记(四)连续线性系统
弹簧阻尼振荡器是一个相对简单的例子,它默认给定一个初始位置后,不再施加外力。拉到一个点,然后弹啊弹啊弹……但是实际上有可能系统会被施加持续的外力,因此需要考虑更复杂的情形。先来定义三个变量:控制量ui...
DiracFatCat 2018-06-04 14:40
【博客大赛】卡尔曼滤波学习笔记(三)状态空间
对一个弹簧阻尼振动器做建模,会发现它的动力学方程是一个二阶表达式:其中,m是负载的质量,t是时间,ks是弹簧系数,kd是阻尼系数。这个表达式就不具体分析了,相信理解起来并不困难。现在将此二阶微分方程转...
我要评论
0
0
广告
关闭 热点推荐上一条 /2 下一条