博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python实现with上下文管理,__exit__()参数exc_type, exc_val, exc_tb异常处理
阅读量:4301 次
发布时间:2019-05-27

本文共 4012 字,大约阅读时间需要 13 分钟。

自己写一下Python的with语句实现

第一种方法利用魔法方法__enter__和__exit__实现:

顾名思义__enter__是打开上文,__exit__关闭下文,相当于打开文件、关闭文件。

#coding=gbk#第一种,魔法方法实现方法class WithContext():    def __init__(self,name=None):        print('接收参数:%r'%name)        self.name=name    def with_context(self):        print(self.name)        print('调用with方法')    def __enter__(self):        print('调用enter方法')        return self    def __exit__(self, exc_type, exc_val, exc_tb):        print('调用exit方法')if __name__ == '__main__':    # 'test_with'作为参数传递给__init__方法    #w为__enter__方法的返回值    with WithContext('test_with') as w:        print('with语句返回值:%r'%w)        print('with语句返回值类型:%r'%type(w))        print(w.name)        w.with_context()

 执行结果:

接收参数:'test_with'

调用enter方法
with语句返回值:<__main__.WithContext object at 0x00000000010B98D0>
with语句返回值类型:<class '__main__.WithContext'>
test_with
test_with
调用with方法
调用exit方法

'test_with'作为参数传递给__init__方法

w为__enter__方法的返回值

可以看出各个方法的执行顺序:

__init__

__exit__

with_context

__exit__

 with语句中的__enter__无返回值的情况:

#coding=gbk#第一种,魔法方法实现方法class WithContext(object):    def __new__(cls,*args,**kwargs):        if not hasattr(cls,'_instance'):            cls._instance=super().__new__(cls)        cls._instance.name='test_with'        return cls._instance    def __init__(self,name=None):        self.name=name        print('接收参数:%r'%name)    def with_context(self):        print(self.name)        print('调用with方法')    def __enter__(self):        print('调用enter方法')    def __exit__(self, exc_type, exc_val, exc_tb):        print('调用exit方法')if __name__ == '__main__':    # 'test_with'作为参数传递给__init__方法    #w为__enter__方法的返回值    with WithContext('test_with') as w:        print('with语句返回值:%r'%w)        print('with语句返回值类型:%r'%type(w))

运行结果: 

接收参数:'test_with'

调用enter方法
with语句返回值:None
with语句返回值类型:<class 'NoneType'>
调用exit方法

顺便说下__exit__方法中的这个三个参数‘exc_type, exc_val, exc_tb’,

异常类型,异常值和异常的trackback

如果with语发生异常,但不希望抛出,__exit__方法应该返回return True,相当于with语句自动做一个try,except处理,

class WithContext(object):    def __init__(self,name=None):        self.name=name        print('接收参数:%r'%name)    def with_context(self):        print(self.name)        print('调用with方法')    def __enter__(self):        print('调用enter方法')        return self    def __exit__(self, exc_type, exc_val, exc_tb):        print(exc_type, exc_val, exc_tb)        print('调用exit方法')        return True        #return Trueif __name__ == '__main__':    # 'test_with'作为参数传递给__init__方法    #w为__enter__方法的返回值    with WithContext('test_with') as w:        #发生异常        a=1/0        #a=1/0        pass

执行结果:

虽然发生异常,但是并没有报错。

接收参数:'test_with'

调用enter方法
<class 'ZeroDivisionError'> division by zero <traceback object at 0x0000000000BAE548>
调用exit方法

如果把return True注释掉,

结果如下:

抛出了异常,打印出了trackback

Traceback (most recent call last):

接收参数:'test_with'
调用enter方法
  File "C:/Users/wangjinyu/PycharmProjects/work_practice/p_103_with_context.py", line 49, in <module>
<class 'ZeroDivisionError'> division by zero <traceback object at 0x000000000081E548>
    a=1/0
调用exit方法
ZeroDivisionError: division by zero

如果把a=1/0注释掉,换成pass,exc_type, exc_val, exc_tb的值均为None

输出结果:

接收参数:'test_with'

调用enter方法
None None None
调用exit方法

 

参考:

官方文档:

object.__exit__(selfexc_typeexc_valuetraceback)

Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be .

If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.

Note that  methods should not reraise the passed-in exception; this is the caller’s responsibility.

 

 blog:

 

第二种方法,用装饰器实现,百度后简单试了下,其实就是利用yield关键字的生成器实现

import contextlib@contextlib.contextmanagerdef with_context(a):    print('执行前')    res=a*a    yield res    print('执行后')if __name__ == '__main__':    #f就是yield 的返回值res    #参数2实参,传递给形参a    with with_context(2) as f:        print(f*f)

执行结果: 

执行前

16
执行后

转载地址:http://icxws.baihongyu.com/

你可能感兴趣的文章
力扣题解-123. 买卖股票的最佳时机 III(动态规划)
查看>>
java中ThreadLocal类的使用
查看>>
java中数组长度为零和为空的区别
查看>>
图解eclipse 查看原始类出现The jar file rt.jar has no source attachment
查看>>
JVM堆内存设置原理
查看>>
约瑟夫问题(java实现)
查看>>
Java 中int、String的类型转换
查看>>
java实现9大排序算法
查看>>
一句话总结java23种设计模式
查看>>
静态表查找
查看>>
乐观锁的一种实现方式——CAS
查看>>
JAVA线程间通信的几种方式
查看>>
IDEA中怎么新建package包,只有directory选项
查看>>
django admin 增加查看权限
查看>>
django后台加载从15秒优化到1秒的过程小记
查看>>
chrome不显示Django-suit左侧菜单栏
查看>>
Python区间库python-intervals
查看>>
django admin 登录用户名密码错误提示
查看>>
python3 AttributeError: 'function' object has no attribute 'func_name'
查看>>
解决ubuntu下修改my.cnf设置字符集导致mysql无法启动
查看>>