广告

Python之异常和工具

2018-4-6 18:56 525 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-09-05 12:14
【博客大赛】卡尔曼滤波学习笔记(11)从位置估计速度
卡尔曼滤波器,不仅仅是一个低通滤波器,否则也不会持续发展50年。 示例:桑先生需要测试高速列车的性能。测试的目的是判断列车在直线上能否保持80m/s的速度。速度和位置每0.1秒测量一次,...
DiracFatCat 2018-08-31 19:32
【博客大赛】卡尔曼滤波学习笔记(10)一个简单的示例
《Kalman Filtering: Theory and Practice Using MATLAB》第三章,看不懂,暂时略过。《Kalman Filtering: Theory and Pract...
DiracFatCat 2018-07-19 15:09
对sed命令的练习
sed是流编辑器。它每次处理一个输入,因此很有效率。官方手册:https://www.gnu.org/software/sed/manual/sed.html学习Linux命令,当然要阅读官方手册,所...
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)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
我要评论
0
0
广告