python入门——天池Task1(day3——异常处理)

python入门——天池Task1(day3异常处理——try/except/else/finally,raise)

5 异常处理

5.1 try - except 语句

表达式:
try:
    检测范围
except Exception[as reason]:
    出现异常后的处理代码

try 语句按照如下方式工作:

1.首先,执行try子句(在关键字try和关键字except之间的语句)
2.如果没有异常发生,忽略except子句,try子句执行后结束。
3.如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和except之后的名 称相符,那么对应的except子句将被执行。最后执行try - except语句之后的代码。
4.如果一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。

异常处理的意义:当程序运行出现错误时,整个程序就会中断,不再向下执行了,异常处理就可以解决这个问题。

【例子1】程序在执行第3行的过程中出现异常,后面的程序也执行不了了

a = 2
print(a)
a = z
print(a)
print("程序在前面异常中断,此句执行不了")

#输出结果为:
'''
2
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-26-c9adf3acc9f8> in <module>
      1 a = 2
      2 print(a)
----> 3 a = z
      4 print(a)
      5 print("程序在前面异常中断,此句执行不了")

NameError: name 'z' is not defined
'''

【例子2】使用try - except语句,除了try下面代码块中,发生异常及其之后的语句不执行(即:a = z
print(a)),后面其他的语句正常执行

try:
    a = 2
    print(a)
    a = z
    print(a)
except:
    print('Error')
print("程序在前面异常中断,此句执行不了")

#输出结果为:
'''
2
Error
程序在前面异常中断,此句执行不了
'''

【例子3】try下面的代码块没有异常发生

try:
    a = 2
    print(a)
except:
    print('Error')
print("程序在前面异常中断,此句执行不了")

#输出结果为:
'''
2
程序在前面异常中断,此句执行不了
'''

从【例子1】,【例子2】以上大致可以知道:
(1)程序先执行try和except之间的代码;
(2)在执行try和except之间的代码时出现错误,就不再继续向下执行了(在a = z时程序出错,后面的print(a)就不再执行了),而是跳转到执行except下的代码块;
(3)最后再继续向下执行。

从【例子3】可以看出:如果try下面的代码块没有异常发生,则except下的代码将会被忽略。

同时也可以存在多个except,分别来处理不同的特定的异常。最多只有一个分支会被执行。
【例子4】
此处使用了3 个except,分别在后面跟了SystemError,NameError,AssertionError,当try下面的代码块运行出错时,可以自动与except后面给出的错误类型进行匹配,并执行相应except代码块下的语句。

try:
    a = 2
    print(a)
    a = z
    print(a)
except SystemError:
    print('SystemError')
except NameError:
    print('NameError')
except AssertionError:
    print('AssertionError')   
print("程序在前面异常中断,此句执行不了")

#输出结果为:
'''
2
NameError
程序在前面异常中断,此句执行不了
'''

【例子5】
当出现的报错与except中的错误类型都不匹配时,又回到了最开始【例子1】一样的情况,此时的try - except是没有起到作用的。

try:
    a = 2
    print(a)
    a = z
    print(a)
except SystemError:
    print('SystemError')
except EnvironmentError:
    print('EnvironmentError')
except AssertionError:
    print('AssertionError')   
print("程序在前面异常中断,此句执行不了")

#输出结果为:
'''
2
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-45-89ba6b3a8bb0> in <module>
      2     a = 2
      3     print(a)
----> 4     a = z
      5     print(a)
      6 except SystemError:

NameError: name 'z' is not defined
'''

【例子6】
使用except而不带任何异常类型,这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息,因为它捕获所有的异常。
为了避免没有匹配到异常,同时有使程序中断,可将代码进行如下修改:

try:
    a = 2
    print(a)
    a = z
    print(a)
except SystemError:
    print('SystemError')
except EnvironmentError:
    print('EnvironmentError')
except AssertionError:
    print('AssertionError')   
except:
    print('报错类型与except中设定的错误类型不匹配')  
print("程序在前面异常中断,此句执行不了")

#输出为:
'''
2
报错类型与except中设定的错误类型不匹配
程序在前面异常中断,此句执行不了
'''

【例子7】

dict1 = {'a': 1, 'b': 2, 'v': 22}
try:
    x = dict1['y']
except LookupError:
    print('查询错误')
except KeyError:
    print('键错误')
else:
    print(x)

#输出为:
'''
查询错误
'''

【例子8】

dict1 = {'a': 1, 'b': 2, 'v': 22}
try:
    x = dict1['y']
except KeyError:
    print('键错误')
except LookupError:
    print('查询错误')
else:
    print(x)

#输出为:
'''
键错误
'''

从【例子7】,【例子8】中可以看出:try-except-else语句尝试查询不在dict中的键值对,从而引发了异常。这一异常准确地说应属于KeyError,但由于KeyError是LookupError的子类,且将LookupError置于KeyError之前,因此程序优先执行该except代码块。所以,使用多个except代码块时,必须坚持对其规范排序,要从最具针对性的异常到最通用的异常。

【例子9】
一个 except 子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组。

try:
    s = 1 + '1'
    int("abc")
    f = open('test.txt')
    print(f.read())
    f.close()
except (OSError, TypeError, ValueError) as error:
    print('出错了!\n原因是:' + str(error))

#输出为:
'''
出错了!
原因是:unsupported operand type(s) for +: 'int' and 'str'
'''

5.2 try - except - else 语句

如果在try子句执行时没有发生异常,Python将执行else语句后的语句。

表达式:
try:
    检测范围
except:
    出现异常后的处理代码
else:
    如果没有异常执行这块代码

【例子10】try子句执行时发生异常,else下的代码块不执行。

try:
    a = 2
    print(a)
    a = x
    print(a)
except SystemError:
    print('SystemError')
except EnvironmentError:
    print('EnvironmentError')
except AssertionError:
    print('AssertionError')   
except:
    print('报错类型与except中设定的错误类型不匹配')  
else:
    print('程序没有错误')
print("程序在前面异常中断,此句执行不了")

#输出为:
'''
2
报错类型与except中设定的错误类型不匹配
程序在前面异常中断,此句执行不了
'''

【例子11】try子句执行时没有发生异常,将执行else下的代码块。

try:
    a = 2
    print(a)
    z = a
    print(z)
except SystemError:
    print('SystemError')
except EnvironmentError:
    print('EnvironmentError')
except AssertionError:
    print('AssertionError')   
except:
    print('报错类型与except中设定的错误类型不匹配')  
else:
    print('程序没有错误')
print("程序在前面异常中断,此句执行不了")

#输出为:
'''
2
2
程序没有错误
程序在前面异常中断,此句执行不了
'''

注意:else语句的存在必须以except语句的存在为前提,在没有except语句的try语句中使用else语句,会引发语法错误。

else作用:没有else语句,当执行完try语句后,无法知道是没有发生异常,还是发生了异常并被处理过了。通过else可以清楚的区分开。

5.3 try - except - finally 语句

不管try子句里面有没有发生异常,finally子句都会执行。

表达式:
try:
	 检测范围 
except Exception[as reason]: 
	出现异常后的处理代码 
finally: 
	无论如何都会被执行的代码

【例子12】
如果一个异常在try子句里被抛出,而又没有任何的except把它截住,那么这个异常会在finally子句执行后被抛出。

def divide(x, y):
    try:
        result = x / y
        print("result is", result)
    except ZeroDivisionError:
        print("division by zero!")
    finally:
        print("executing finally clause")


divide(2, 1)
# result is 2.0
# executing finally clause
divide(2, 0)
# division by zero!
# executing finally clause
divide("2", "1")
# executing finally clause
# TypeError: unsupported operand type(s) for /: 'str' and 'str'

#输出为:
'''
result is 2.0
executing finally clause
division by zero!
executing finally clause
executing finally clause
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-57-16805cf48925> in <module>
     15 # division by zero!
     16 # executing finally clause
---> 17 divide("2", "1")
     18 # executing finally clause
     19 # TypeError: unsupported operand type(s) for /: 'str' and 'str'

<ipython-input-57-16805cf48925> in divide(x, y)
      1 def divide(x, y):
      2     try:
----> 3         result = x / y
      4         print("result is", result)
      5     except ZeroDivisionError:

TypeError: unsupported operand type(s) for /: 'str' and 'str'
'''

【例子13】try - finally 也可以单用。
同样的,异常要在finally下的代码块执行完之后才抛出。

try:
    x = y
    print(x)
finally:
    print('无论try下面的代码块是否发生错误,finally下的代码块都会执行')
print("程序在前面异常中断,此句执行不了")

#输出为:
'''
无论try下面的代码块是否发生错误,finally下的代码块都会执行
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-58-5d85bca8aabd> in <module>
      1 try:
----> 2     x = y
      3     print(x)
      4 finally:
      5     print('无论try下面的代码块是否发生错误,finally下的代码块都会执行')

NameError: name 'y' is not defined
'''

5.6 raise 语句

Python 使用raise语句人为的抛出一个指定的异常。

程序发生异常和程序执行错误,它们完全是两码事,程序由于错误导致的运行异常,是需要程序员想办法解决的;但还有一些异常,是程序正常运行的结果,比如用 raise 手动引发的异常。

raise 语句的基本语法格式为:
raise [exceptionName [(reason)]]

其中,用 [] 括起来的为可选参数,其作用是指定抛出的异常名称,以及异常信息的相关描述。如果可选参数全部省略,则 raise 会把当前错误原样抛出;如果仅省略 (reason),则在抛出异常时,将不附带任何的异常描述信息。

也就是说,raise 语句有如下三种常用的用法:
1.raise:单独一个 raise。该语句引发当前上下文中捕获的异常(比如在 except 块中),或默认引发 RuntimeError 异常。
2.raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常。
3.raise 异常类名称(描述信息):在引发指定类型的异常的同时,附带异常的描述信息。

【例子14】raise引发异常的三种情况
在这里插入图片描述
【例子15】

try:
    a = input("输入一个数:")
    #判断用户输入的是否为数字
    if(not a.isdigit()):
        raise ValueError("a 必须是数字")
except ValueError as e:
    print("引发异常:",repr(e))

#输出为:
'''
输入一个数:a
引发异常: ValueError('a 必须是数字')
'''

可以看到,当用户输入的不是数字时,程序会进入 if 判断语句,并执行 raise 引发 ValueError 异常。但由于其位于 try 块中,因为 raise 抛出的异常会被 try 捕获,并由 except 块进行处理。

因此,虽然程序中使用了 raise 语句引发异常,但程序的执行是正常的,手动抛出的异常并不会导致程序崩溃。

【例子16】

try:
    a = input("输入一个数:")
    if(not a.isdigit()):
        raise ValueError("a 必须是数字")
except ValueError as e:
    print("引发异常:",repr(e))
    raise

#输出为:
'''
输入一个数:a
引发异常: ValueError('a 必须是数字')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-28-8ee213d8d387> in <module>
      2     a = input("输入一个数:")
      3     if(not a.isdigit()):
----> 4         raise ValueError("a 必须是数字")
      5 except ValueError as e:
      6     print("引发异常:",repr(e))

ValueError: a 必须是数字
'''

这里重点关注位于 except 块中的 raise,由于在其之前我们已经手动引发了 ValueError 异常,因此这里当再使用 raise 语句时,它会再次引发一次。

【例子17】当在没有引发过异常的程序使用无参的 raise 语句时,它默认引发的是 RuntimeError 异常。如下:

try:
    a = input("输入一个数:")
    if(not a.isdigit()):
        raise
except RuntimeError as e:
    print("引发异常:",repr(e))

#输出为:
'''
输入一个数:a
引发异常: RuntimeError('No active exception to reraise')
'''

【例子18】

def get_age():
    age = int(input('请输入年龄(1-140):'))
    if age in range(1, 141):
        return age
    raise ZeroDivisionError  # 故意抛出异常
try:
    age = get_age()
    print('用户输入的年龄是:', age)
except ZeroDivisionError as err:  # 接收抛出的异常
    print('用户输入的年龄不在1-140之间,获取年龄失败!')

#输出为:
'''
请输入年龄(1-140):0
用户输入的年龄不在1-140之间,获取年龄失败!
'''

当输入年龄不在[1~140]之间时,get_age()函数的raise就会抛出一个异常,然后except在接受在上面try代码块中get_age()函数中raise抛出的异常。

Python raise用法
python try语句相关(try/except/else/finally)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值