zoukankan      html  css  js  c++  java
  • Python学习笔记9——异常处理

    处理异常

    如果执行到程序中某处抛出了异常,程序就会被终止并退出。你可能会问,那有没有什么办法可以不终止程序,让其照样运行下去呢?答案当然是肯定的,这也就是我们所说的异常处理,通常使用 try 和 except 来解决,比如:

     1 try:
     2     s = input('please enter two numbers separated by comma: ')
     3     num1 = int(s.split(',')[0].strip())
     4     num2 = int(s.split(',')[1].strip())
     5     ... 
     6 except ValueError as err:
     7     print('Value Error: {}'.format(err))
     8  
     9 print('continue')
    10 ...

    这里默认用户输入以逗号相隔的两个整形数字,将其提取后,做后续的操作(注意 input 函数会将输入转换为字符串类型)。如果我们输入a,b,程序便会抛出异常invalid literal for int() with base 10: 'a',然后跳出 try 这个 block。

    由于程序抛出的异常类型是 ValueError,和 except block 所 catch 的异常类型相匹配,所以 except block 便会被执行,最终输出Value Error: invalid literal for int() with base 10: 'a',并打印出continue

    please enter two numbers separated by comma: a,b
    Value Error: invalid literal for int() with base 10: 'a'
    continue

    except block 只接受与它相匹配的异常类型并执行,如果程序抛出的异常并不匹配,那么程序照样会终止并退出。

    所以,还是刚刚这个例子,如果我们只输入1,程序抛出的异常就是IndexError: list index out of range,与 ValueError 不匹配,那么 except block 就不会被执行,程序便会终止并退出(continue 不会被打印)。

    please enter two numbers separated by comma: 1
    IndexError Traceback (most recent call last)
    IndexError: list index out of range

    不过,很显然,这样强调一种类型的写法有很大的局限性。那么,该怎么解决这个问题呢?

    其中一种解决方案,是在 except block 中加入多种异常的类型,比如下面这样的写法:

     1 try:
     2     s = input('please enter two numbers separated by comma: ')
     3     num1 = int(s.split(',')[0].strip())
     4     num2 = int(s.split(',')[1].strip())
     5     ...
     6 except (ValueError, IndexError) as err:
     7     print('Error: {}'.format(err))
     8     
     9 print('continue')
    10 ...

    或者第二种写法:

     1 try:
     2     s = input('please enter two numbers separated by comma: ')
     3     num1 = int(s.split(',')[0].strip())
     4     num2 = int(s.split(',')[1].strip())
     5     ...
     6 except ValueError as err:
     7     print('Value Error: {}'.format(err))
     8 except IndexError as err:
     9     print('Index Error: {}'.format(err))
    10  
    11 print('continue')
    12 ...

    这样,每次程序执行时,except block 中只要有一个 exception 类型与实际匹配即可。

    不过,很多时候,我们很难保证程序覆盖所有的异常类型,所以,更通常的做法,是在最后一个 except block,声明其处理的异常类型是 Exception。Exception 是其他所有非系统异常的基类,能够匹配任意非系统异常。那么这段代码就可以写成下面这样:

     1 try:
     2     s = input('please enter two numbers separated by comma: ')
     3     num1 = int(s.split(',')[0].strip())
     4     num2 = int(s.split(',')[1].strip())
     5     ...
     6 except ValueError as err:
     7     print('Value Error: {}'.format(err))
     8 except IndexError as err:
     9     print('Index Error: {}'.format(err))
    10 except Exception as err:
    11     print('Other error: {}'.format(err))
    12  
    13 print('continue')
    14 ...

    或者,你也可以在 except 后面省略异常类型,这表示与任意异常相匹配(包括系统异常等):

     1 try:
     2     s = input('please enter two numbers separated by comma: ')
     3     num1 = int(s.split(',')[0].strip())
     4     num2 = int(s.split(',')[1].strip())
     5     ...
     6 except ValueError as err:
     7     print('Value Error: {}'.format(err))
     8 except IndexError as err:
     9     print('Index Error: {}'.format(err))
    10 except:
    11     print('Other error')
    12  
    13 print('continue')
    14 ...

    需要注意,当程序中存在多个 except block 时,最多只有一个 except block 会被执行。换句话说,如果多个 except 声明的异常类型都与实际相匹配,那么只有最前面的 except block 会被执行,其他则被忽略。

    异常处理中,还有一个很常见的用法是 finally,经常和 try、except 放在一起来用。无论发生什么情况,finally block 中的语句都会被执行,哪怕前面的 try 和 excep block 中使用了 return 语句。

    一个常见的应用场景,便是文件的读取:

     1 import sys
     2 try:
     3     f = open('file.txt', 'r')
     4     .... # some data processing
     5 except OSError as err:
     6     print('OS error: {}'.format(err))
     7 except:
     8     print('Unexpected error:', sys.exc_info()[0])
     9 finally:
    10     f.close()

    这段代码中,try block 尝试读取 file.txt 这个文件,并对其中的数据进行一系列的处理,到最后,无论是读取成功还是读取失败,程序都会执行 finally 中的语句——关闭这个文件流,确保文件的完整性。因此,在 finally 中,我们通常会放一些无论如何都要执行的语句。

    值得一提的是,对于文件的读取,我们也常常使用 with open,你也许在前面的例子中已经看到过,with open 会在最后自动关闭文件,让语句更加简洁。

    自定义异常

    前面的例子里充斥了很多 Python 内置的异常类型,你可能会问,我可以创建自己的异常类型吗?

    答案是肯定是,Python 当然允许我们这么做。下面这个例子,我们创建了自定义的异常类型 MyInputError,定义并实现了初始化函数和 str 函数(直接 print 时调用):

     1 class MyInputError(Exception):
     2     """Exception raised when there're errors in input"""
     3     def __init__(self, value): # 自定义异常类型的初始化
     4         self.value = value
     5     def __str__(self): # 自定义异常类型的 string 表达形式
     6         return ("{} is invalid input".format(repr(self.value)))
     7     
     8 try:
     9     raise MyInputError(1) # 抛出 MyInputError 这个异常
    10 except MyInputError as err:
    11     print('error: {}'.format(err))

    如果你执行上述代码块并输出,便会得到下面的结果:

    1 error: 1 is invalid input

    实际工作中,如果内置的异常类型无法满足我们的需求,或者为了让异常更加详细、可读,想增加一些异常类型的其他功能,我们可以自定义所需异常类型。不过,大多数情况下,Python 内置的异常类型就足够好了。

  • 相关阅读:
    Linux驱动下的platform总线架构(转)
    一生中很值得看的30个故事之一断箭
    学习嵌入式LINUX系统的笔记和体会
    DIY:自己动手做一个迷你 Linux 系统
    linux里面i386 i686 i486 i586代表什么?是什么意思
    菜鸟编译Linux内核
    LINUX核心重编与升级
    ARM 内核移植中常见的错误
    Linux 2.6.19.x 内核编译配置选项简介
    基于S3C2410平台移植Linux 2.6内核指南
  • 原文地址:https://www.cnblogs.com/yuanxixing/p/12373526.html
Copyright © 2011-2022 走看看