【python教程】4、定义、引发创建、捕获异常

1、什么是异常

python使用异常对象来表示异常状态,并在遇到错误时引发异常。异常对象未被处理或捕获时,程序将终止并显示一条错误消息(traceback)。如下:

>>> 1/0
Traceback(most recent call last):
 File"<stdin>", line 1, in?
ZeroDivisionError.integer division or modulo by zero

每个异常都是某个类(如ZeroDivisionError)的实例,我们可以以各种方式引发和捕获这些实例,从而逮住错误并采取措施,而不是放任整个程序失败。

2、引发和创建异常

raise语句引发异常:将一个类(必须是Exception的子类)或实例作为参数。

raise Exception  # 将类作为参数时,将自动创建一个实例。这里引发的是通用异常,没有指出出现了什么错误。
raise Exception('hyperdrive overload')  # 添加了错误消息hyperdrive overload

比较重要的一些内置的异常类:

Exception:几乎所有的异常类都是从它派生而来的
AttributeError:引用属性或给他赋值失败时引发
OSError:操作系统不能执行指定的任务(如打开文件)时引发,有多个子类
indexError:使用序列中不存在的索引时引发,为LookupError的子类
KeyError:使用映射中不存在的键时引发,为LookupError的子类
NameError:找不到名称(或变量)时引发
SyntaxError:代码不正确时引发
TypeError:将内置操作或函数用于类型不正确的对象时引发
ValueError:将内置操作或函数用于这样的对象时引发:其类型正确但包含的值不合适
ZeroDivisionError:在除法或求模运算的第二个参数为0时引发

3、捕获异常

异常有趣的地方是可对其进行处理,称之为捕获异常。常用:try/except语句。基本用法:

# 一:捕获异常并对错误进行处理(打印友好的错误消息)
try:
    x = int(input('first number:'))
    y = int(input('second number:'))
    print(x / y)
except ZeroDivisionError:
    print("the second number can't be zero!")
	
# 二:捕获异常后,抑制异常
class MuffledCalculator:
    muffled = False
    def calc(self, expr):
        try:
            return eval(expr)
	except ZeroDivisionError:
	    if self.muffled:  # 与用户交互时,启用抑制功能,不让异常继续传播
		print('Division by zero is illegal')
	    else:  # 在程序内部使用时,关闭抑制功能,引发异常
		raise
# 注意:发生除零行为,若启用抑制功,calc将隐式地返回None。

# 三:在except子句中,引发别的异常
try:
    1 / 0
except ZeroDivisionError:
    raise ValueError  # 进行except子句的异常将被作为异常上下文存储起来,并出现在最终的错误消息中

# 四:使用None来禁用上下文
try:
    1 / 0
except ZeroDivisionError:
    raise ValueError from None

# 执行结果如下:
Traceback(most recent call last):
    File"<stdin>", line 3, in <module>
ValueError

其他用法:

# 一、多个except子句,捕获多种异常
try:
    x = int(input('first number:'))
    y = int(input('second number:'))
    print(x / y)
except ZeroDivisionError:
    print("the second number can't be zero!")
except TypeError:
    print("That wasn't a number, was it")
	
# 二、一个except子句捕获多个异常,可在元组中指定异常(一个参数)
try:
    x = int(input('first number:'))
    y = int(input('second number:'))
    print(x / y)
except (ZeroDivisionError, TypeError, NameError):
    print("your numbers were bogus ...")

# 三、捕获异常对象本身(可使用两个参数)
try:
    x = int(input('first number:'))
    y = int(input('second number:'))
    print(x / y)
except (ZeroDivisionError, TypeError) as e:
    print(e)  # 打印异常并继续运行
	
# 四、捕获所有异常,在except中不指定任何异常类即可
try:
    x = int(input('first number:'))
    y = int(input('second number:'))
    print(x / y)
except:
    print('something wrong happened ...')
# 这种做法很危险,会捕获到用户使用ctrl+c或调用函数sys.exit来终止执行的企图等。推荐使用except Exception as e对异常对象进行检查。(可能会让不是从Exception派生而来的异常漏网,如SystemExit、KeyboardInterrupt,他们是从Exception的超类BaseException派生而来)

# 五、给try/except添加else子句和finally:没有出现异常时会执行else中代码块
x = None
try:
    x = 1 / 0
except NameError:
    print('unknown variable')
else:
    print("that went well!")
finally:
    print("cleaning up...")
    del x  # 发生异常时,执行finally子句清理工作(适用于确保文件或网络套接字等得以关闭)

4、异常之禅

很多情况下,相比使用if/else,使用try/except语句更自然,也更符合python风格。(直接去做,有问题在处理,而不是预先做大量的检查)

posted @ 2021-07-27 21:03  --D  阅读(82)  评论(0编辑  收藏  举报