前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【AICAMP —— Python】入门系列!(5. 异常与处理)

【AICAMP —— Python】入门系列!(5. 异常与处理)

作者头像
灿视学长
发布2021-05-28 11:15:57
3690
发布2021-05-28 11:15:57
举报
文章被收录于专栏:灿视学长

异常与处理

1. 错误处理

在我们写程序过程中,往往不是一次性就能写出很好的代码,会因为各种问题,程序发生错误

因此我们在写代码的时候,往往会花很多时间在错误处理上。一种方法是我们自己定义错误码,根据返回的错误码,来进行相对应的操作。

如:

代码语言:javascript
复制
def function():
    r = some_return_value()
    if r==(-1):
        return (-1)
    # do something
    return r

然而这样的处理十分复杂,我们需要加很多后处理。python中有异常处理try...except...finally...的错误处理机制。

比如,对于一个数除以0:

代码语言:javascript
复制
try:
    print('try...')
    r = 1 / 0
    print('result is:', r)
except ZeroDivisionError as e:
    print('except:', e)
finally:
    print('finally...')
print('END')

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

上述代码输出内容为:

代码语言:javascript
复制
try...
except: division by zero
finally...
END

当错误发生时,后续语句print('result:', r)不会被执行,except由于捕获到ZeroDivisionError,因此被执行。最后,finally语句被执行。然后,程序继续按照流程往下走。

如果我们把0换成了2,那么结果为:

代码语言:javascript
复制
try...
result: 5
finally...
END

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

错误应该有很多种类,如果发生了不同类型的错误,应该由不同的except语句块处理。没错,可以有多个except来捕获不同类型的错误。此外,如果没有错误发生,可以在except语句块后面加一个else,当没有错误发生时,会自动执行else语句:

代码语言:javascript
复制
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...except...finally的麻烦。我们可以用一张图来总结下try...except...else...finally的执行顺序:

同时,Python中内置的错误有这些:

  • AttributeError: 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x
  • IOError: 输入/输出异常;基本上是无法打开文件
  • ImportError: 无法引入模块或包;基本上是路径问题或名称错误
  • IndentationError: 语法错误(的子类) ;代码没有正确对齐
  • IndexError: 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
  • KeyError: 试图访问字典里不存在的键
  • KeyboardInterrupt: Ctrl+C被按下
  • NameError: 使用一个还未被赋予对象的变量
  • **SyntaxError:**代码非法,代码不能编译(个人认为这是语法错误,写错了)
  • TypeError: 传入对象类型与要求的不符合
  • UnboundLocalError: 试图访问一个还未被设置的局部变量,基本上是由于另有一 个同名的全局变量,导致你以为正在访问它
  • ValueError: 传入一个调用者不期望的值,即使值的类型是正确的

2. 抛出错误

Python 使用 raise 语句抛出一个指定的异常。 如下抛出一个异常:

代码语言:javascript
复制
x = 10
if x > 5:
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))

则以上的代码就会抛出一个异常:

代码语言:javascript
复制
Traceback (most recent call last):
  File "test.py", line 3, in <module>
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
Exception: x 不能大于 5。x 的值为: 10

因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。Python的内置函数会抛出很多类型的错误,我们自己编写的函数也可以抛出错误。

目前抛出的错误都是系统中实现的错误,如果要抛出一个我们自己想要设计的错误,首先根据需要,可以定义一个错误的class,选择好继承关系,然后,用raise语句抛出一个错误的实例:

代码语言:javascript
复制
# err_raise.py
class MyError(ValueError):
    pass

def foo(s):
    n = int(s)
    if n==0:
        raise MyError('invalid value: %s' % s)
    return 10 / n

foo('0')

执行代码,则可以在最后跟踪到我们自定义的错误:

代码语言:javascript
复制
$ python3 err_raise.py 
Traceback (most recent call last):
  File "err_throw.py", line 11, in <module>
    foo('0')
  File "err_throw.py", line 8, in foo
    raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0

只有在必要的时候才定义我们自己的错误类型。如果可以选择Python已有的内置的错误类型(比如ValueError,TypeError),尽量使用Python内置的错误类型。

我们也可以嵌套异常处理,当我们当前函数无法很好的处理异常的时候,我们可以把异常再往上raise,如代码:

代码语言:javascript
复制
try:
    10 / 0
except ZeroDivisionError:
    raise ValueError('input error!')

我们就可以把除以0的异常往值错误这样更宽泛错误上进行抛。

3. assert断言

在python中,assert可以用于判断一个表达式,在表达式条件为false的时候触发异常。 断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况,例如我们的代码只能在Linux 系统下运行,可以先判断当前系统是否符合条件。 代码举例:

代码语言:javascript
复制
>>> assert 1 == 1 #条件为True,则正常执行
>>> assert 1 == 2, '1不等于2'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: 1 不等于 2

或者如我们判别当前是不是linux系统:

代码语言:javascript
复制
>>> import sys
>>> assert ('linux' in sys.platform), '非linux系统'
>>> ...#其它代码

4. 总结

在调试代码的时候,我们可以先用assert来判断代码是否正常,如果不正常,assert可以退出程序,再进行排查。再来,我们可以用try ... except 配合raise的机制来进行代码的异常处理。

5. 关于我

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 灿视学长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 异常与处理
    • 1. 错误处理
      • 2. 抛出错误
        • 3. assert断言
          • 4. 总结
            • 5. 关于我
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档