python学习笔记--异常

目录

1.异常对象

1.1内置异常类

1.2用户定义异常类

2.异常处理语句

2.1try/except/else/finally语句

2.2raise语句

2.2.1异常链

2.2.2禁用异常链 

2.3assert语句

2.4with/as语句

2.4.1基本用法

2.4.2创建上下文管理器 


1.异常对象

 在 Python 中,所有异常必须为一个派生自 BaseException 的类的实例。

1.1内置异常类

BaseException:异常的顶级根父类,它提供了子类可继承的默认打印和状态保持行为。

Exception:它是 BaseException 类的一个直接子类,并且是除系统退出事件类外 (SystemExit、KeyboardInterrupt 和 GeneratorExit),所有其他内置异常的父类。用户定义异常类应该继承自这个类或它的子类

其他异常类:ArithmeticError,LookupError等

传递给这些类的任何构造函数参数都会自动保存在实例的 args 元组属性中,并且会在打印该实例的时候自动显示。

1.2用户定义异常类

class MyException(Exception):
    def __init__(self,line,file): #定制的数据
        self.line = line
        self.file = file

    def __str__(self):        #定制的打印显示
        return "Bad"

2.异常处理语句

2.1try/except/else/finally语句

try:
    ...
except name: #捕捉指定的异常
    ...
except (name1,name2): #捕捉列出的任一异常
    ...
except name as value: #捕捉异常并赋值给value
    ...
except (name1,name2) as value: #捕捉异常并将异常实例元组赋值给value
    ...
except Exception: #捕捉除系统退出异常外的所有异常
    ...
except:  #捕捉所有其他异常,可调用sys.exc_info()访问异常信息
    ...
else:     #没有异常时执行;[可选]
    ...
finally:  #有无异常都会执行;不会终止异常,会继续向上传递;[可选]
    ...   #可执行一些清理操作,如释放资源
  • except语句as后面的变量名,仅限于except对应的语句块中使用。 
  • 特定类的except子句,也会捕获任何派生自该类的异常类。
  • 空的except语句:捕获所有异常,可能捕获属于其他处理程序的异常或意外的系统异常。
  • Exception:捕获所有异常,但忽略与系统退出相关的异常。 
  • sys.exc_info(): 如果有异常,返回(type, value, traceback),否则,返回三个None值。    type--正在处理的异常的类型, value--被引发的异常类实例,traceback--代表异常最初发生时所调用栈,同时被traceback模块用来产生错误信息。通常在空except使用访问异常信息。

传播机制:

如果异常不能与当前 try 语句的任何 except 分句相匹配,那么异常就会沿着调用栈向上传播,直到找到匹配的except块,或者到达程序的顶层导致程序终止。

2.2raise语句

 使用raise语句显式地触发异常,raise后面跟着可选的异常实例或异常类(隐式创建实例)。

raise instance   #异常实例
raise classtype  #内部会调用构造函数创建实例
raise            #重新引发最近触发的异常

2.2.1异常链

raise newexception from otherexception

用其他异常引发新的异常,otherexception会附加到newexception的__cause__属性上。如果新的异常没有被捕获,都会被打印出来。

示例:

2.2.2禁用异常链 

raise newexception from None

使用from None 可以显示更少的错误信息 。

示例:

2.3assert语句

assert test,data

assert可视为有条件的raise语句,test为false时引发异常,data作为异常构造函数的参数。

内部执行如下:

if __debug__:   #__debug__是内置名称,除非使用-O运行程序,否则默认为True
    if not test:
        raise AssertionError(data)

assert主要用于捕获用户输入的约束条件,而不是程序设计错误,因为python遇到程序设计错误会自动引发异常。  

可使用类似Python -O(优化模式) main.py 运行程序,关闭assert。

2.4with/as语句

with跟C#语言中的using语句类似,是try/finally的替代方案,用于必须执行的终止或清理行为。

with语句的目的是配合上下文管理器对象一起工作。python为一些内置工具增加了上下文管理器,如自动自行关闭的文件,线程锁的自动上锁和解锁。

2.4.1基本用法

with expression [as variable]:  #expression要返回一个上下文管理器
    ...

示例:文件对象有上下文管理器(代码块结束自动关闭文件)

with open(r'C:\mydata') as myfile:
    for line in myfile:
        print(line)

示例:多个上下文管理器

with open('data') as fin,open('res','w') as fout:
    for line in fin:
        if 'key' in line:
            fout.write(line)

2.4.2创建上下文管理器 

1)实现魔法方法

  • 实现__enter____exit__方法,分别在with代码块进入和退出时执行。
  • 如果有as分句,__enter__的返回结果赋值给as分句的变量。 
  • 如果with代码块引发异常,__exit __(type, value, traceback) 方法就会被调用 (该方法会携带异常细节)。它们与 sys. exc_info 调用所返回的三个值相同。__exit__的返回结果为False,异常会重新引发,结果为True,异常会终止(异常已处理,返回True,未处理,返回False)。
  • 如果 with 代码块没有引发异常,__exit__ 方法依然会被调用,其 type、value 以及 traceback 参数都为 None 。

示例:创建上下文管理器 

class TraceBack:
    def message(self,msg):
        print('running ' + msg)
    def __enter__(self):
        print('enter ...')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            print("exited normally")
        else:
            print('raise an exception ' + str(exc_type))
        #默认返回值None,为False,异常向上传播
with TraceBack() as action:
    action.message('test 1')
    print('reached')

with TraceBack() as action:
    action.message('test 2')
    raise TypeError
    print('unreached')

2)使用contextlib

 @contextlib.contextmanager装饰器,它可用来简化上下文管理器的编写,它可被用来定义一个支持 with语句上下文管理器的工厂函数,而无需创建一个类或单独的__enter__和__exit__方法。 

示例: 

from contextlib import contextmanger

@contextmanger
def file_manger(filename, mode):
    try:
        f = open(filename, mode)
        yield f        #yield值绑定到as后面的变量
    finally:
        f.close()   #进行了清理操作,如果with内部的代码块发生异常,异常向上传播;               
                    # 可以使用 try/except捕获异常

#使用上下文管理器
with file_manger('exapmle.txt', 'w') as f:
    f.write('Hello, World')

 yield语句之前的代码相当于__enter__方法的内容,yield之后的代码相当于__exit__方法的内容。

被装饰的函数在被调用时,必须返回一个迭代器。 这个迭代器必须只 yield 一个值出来。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值