Python学习第16天:Python 错误和异常[3]

224 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情 >>

异常的参数

except 子句可以在异常名称后面指定一个变量。这个变量和一个异常实例绑定,它的参数是一个元组,通常包含错误字符串,错误数字,错误位置,存储在 .args 中。为了方便起见,异常实例定义了__str__() ,因此可以直接打印参数而无需引用 .args。

try:
    # 正常的操作 ......
except ExceptionType as inst:
    # 可以在这输出 inst 的值.....
实例
try:
    x = 1 / 0  # 除数为0
except ZeroDivisionError as err: #为异常指定变量err
    print("Exception")
    print(err.args) #打印异常的参数元组
    print(err) #打印参数,因为定义了__str__()

#输出
Exception
('division by zero',)
division by zero

触发异常

Python 提供了 raise 语句用于手动引发一个异常。

语法
raise [Exception [, args [, traceback]]]
参数说明
Exception:异常的类型,例如 ZeroDivisionError
args:异常参数值,可选,默认值 "None"
traceback:可选,用于设置是否跟踪异常对象

异常参数值可以是一个字符串,类或对象

实例
def diyException(level):
    if level > 0:
        raise Exception("raise exception", level)  #主动抛出一个异常,并且带有参数
        print('我是不会执行的') #这行代码不会执行

try:
   diyException(2)  #执行异常方法
except Exception as err: #捕获异常
    print(err) #打印异常参数
    
#输出
('raise exception', 2)

为了能够捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。如果要捕获上面代码抛出的异常,except 语句应该如下所示:

#定义函数
def diyException(level):
    if level > 0:
        raise Exception("error level", level)  #主动抛出一个异常,并且带有参数
        print('我是不会执行的') #这行代码不会执行

try:
   diyException(2)  #执行异常方法
except 'error level' as err: #捕获异常
    print(err) #打印异常参数

#输出
Traceback (most recent call last):
  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module>
    diyException(2)  #执行异常方法
  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException
    raise Exception("error level", level)  #主动抛出一个异常,并且带有参数
Exception: ('error level', 2)

当然,我们也可以通过 traceback 来捕获异常:

import traceback

#定义函数
def diyException(level):
    if level > 0:
        raise Exception("error level", level)  #主动抛出一个异常,并且带有参数
        print('我是不会执行的') #这行代码不会执行

try:
   diyException(2)  #执行异常方法
except Exception: #捕获异常
    traceback.print_exc()
#输出
Traceback (most recent call last):
  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module>
    diyException(2)  #执行异常方法
  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException
    raise Exception("error level", level)  #主动抛出一个异常,并且带有参数
Exception: ('error level', 2)

用户自定义异常

除了使用 Python 内置的异常,我们还可以创建自己的异常类型。创建自己的异常非常简单,只需要创建一个类,并继承 Exception 类或其子类。

下面的代码创建了一个异常 DiyError 继承自 Python 内置的 RuntimeError,用于在异常触发时输出更多的信息。

#自定义异常
class DiyError(RuntimeError):
    def __init__(self, arg):
        self.args = arg

try:
    raise DiyError("my diy exception") #触发异常
except DiyError as e:
    print(e)

定义好了之后,我们就可以在 except 语句后使用 DiyError 异常,变量 e 是用于创建 DiyError 类的实例。我们也可以通过 raise 语句手动触发这个异常。

预定义的清理行为

一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行。

for line in open("myfile.txt"):
    print(line, end="")

上面这个例子尝试打开一个文件,然后把内容打印出来。但是有一个问题:当执行完毕后,程序没有关闭文件流,文件会保持打开状态。

关键词 with 语句就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法。

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

以上这段代码执行完毕后,就算在处理过程中出问题了,文件 f 总是会关闭。这里面的原理就是使用了 finally 机制,有兴趣的可以去深入了解一下。