Python异常处理

异常处理

try…except语句用于异常处理。

>>> while True:
...     try:
...         x = int(input("Please enter a number: "))
...         break
...     except ValueError:
...         print("Oops!  That was no valid number.  Try again...")

可以有多个except字句,也可以同时指定多种异常

... except (RuntimeError, TypeError, NameError):
...     pass

异常继承匹配

父类可以捕获子类异常

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")

打印输出B,C,D。如果except倒序为B,C,D则打印输出B,B,B。

匹配任意异常

最后的except字句可以省略异常类型,实现捕获任意异常的功能

import sys
try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise #reraise this exception

else子句

可以附加一个else子句在try…except语句的最后(finally之前),else是可选的,但是必须位于所有except之后,表示如果try中的语句没有异常产生,则else中的内容被执行。

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

finally子句

可选的finally字句必须位于try语句的最后,但是和else不同,finally之前可以没有except和else,无论try子句中是否有异常抛出,在离开try语句前finally里的内容都会被执行。

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     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
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

如果try子句或者之后的except或者else子句有没有被捕获的异常产生,finally执行后,该异常会被自动再次抛出。通过break,continue,return在离开try语句前,finally也会被执行,如果finally中有return,那么finally中return的值会被返回,而非try,except,else中return的值。

finally子句通常用于清理工作,无论资源的使用情况是否成功,最后都释放掉资源。

异常变量

except语句可以指定异常变量,捕获具体的异常实例对象,异常实例对象的args属性存储着和异常相关的数据。

>>> try:
...      raise Exception('spam', 'eggs')
...     except Exception as inst:
...      print(type(inst))    # the exception instance
...      print(inst.args)     # arguments stored in .args
...      print(inst)          # __str__ allows args to be printed directly,
...                          # but may be overridden in exception subclasses
...      x, y = inst.args     # unpack args
...      print('x =', x)
...      print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

抛出异常

raise关键字用于抛出异常

>>> raise NameError('HiThere')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: HiThere

raise之后可以是异常实例对象或者是异常类型,如果是异常类型,该类型的默认构造器被自动调用用于实例化一个异常对象

raise ValueError  # shorthand for 'raise ValueError()'

except字句中,重抛出被捕获的异常,可以简单的使用raise

>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
...
An exception flew by!Traceback (most recent call last):
File "<stdin>", line 2, in <module>NameError: HiThere

自定义异常

通过直接或非直接继承Exception类,可以定义自己的异常类型

class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class InputError(Error):
    """Exception raised for errors in the input.

    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """

    def __init__(self, expression, message):
        self.expression = expression
        self.message = message

class TransitionError(Error):
    """Raised when an operation attempts a state transition that's not
    allowed.

    Attributes:
        previous -- state at beginning of transition
        next -- attempted new state
        message -- explanation of why the specific transition is not allowed
    """

    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message

和内建的标准异常类型类似,一般异常类型都以Error结尾,每个不同的模块都有自己的异常基类,该模块中可能出现的具体异常类型则由该异常基类导出。

预定义了清理动作的对象

一些对象需要在不再被需要时执行特定的清理动作,可以用try…exception…finally语句确保这些清理动作得到执行。

不过更加简洁高效安全的做法是对这类对象使用with…as语句声明,with…as…将在其中的执行体执行完毕,或者中途抛出异常时确保其预定义的清理动作一定得到调用,支持此类用法的对象都有close方法,其中预定义了该对象的清理操作。

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值