python学习笔记整理tcy1: with上下文管理

上下文管理器类型 2018/7/8

https://docs.python.org/3.7/library/

参考书:Python参考手册+第4版_修订版

--------------------------------------------------------------------------

1.自定义上下文管理器

定义:

class list_withFun(object):

    def__init__(self,lst):

       self.lst=lst

    def__enter__(self):

      self.old_data=list(self.lst)

      return self.old_data

    def__exit__(self,type,value,trackback):

       if type is None:

           self.lst[:]=self.old_data

       return True

调用1:

items=[1,2,3]

with list_withFun(items) as s:

   s.append(4)

   s.append(5)

   print(items)

调用2

try:

   with list_withFun(items) as s:

       s.append(6)

       s.append(7)

       raise RuntimeError('we are hosed')

       print('error')

except RuntimeError:

   pass

print(items)

##

***********************************************************

定义:

from contextlib import contextmanager

@contextmanager

def list_withFun1(lst):

   old_data=list(lst)   #yield 语句前:初始化资源

   yield old_data       #返回值

   lst[:]=old_data      #yield 语句后:释放资源,处理异常

调用

items=[11,12,13]

with list_withFun(items) as s:

   s.append(14)

   s.append(15)

   print(items)

------------------------------------------------------------------------------

2.应用

with 语句适用对资源访问场合(上下文管理器对象),确保不管使用过程中是否发生

异常都执行清理,释放资源,如文件用后自动关闭、线程中锁自动获取和释放等。

对象有:

file;decimal.Context;thread.LockType;threading.Lock;threading.Rlock;

threading.Condition;threading.Semaphore;threading.BoundedSemaphore

------------------------------------------------------------------------------

3.1.语法格式:

contextmanager.__enter__()

输入运行时此方法返回的值绑定到使用此上下文管理器aswith语句子句中的标识符。

 

contextmanager.__exit__(exc_type,exc_val,exc_tb )

退出运行返回bool,是否抑制发生异常。True异常忽略;False重新抛出异常

执行with语句正文发生异常,参数包含异常类型,值和追溯信息或3个None。

withcontext_expression [as target(s)]:

    with-body

参数:

context_expression 要返回一个上下文管理器对象;

__enter__() 方法的返回值赋值给 target(s)。target(s) 是单变量,或者由“()”括起来的元组

------------------------------------------------------------------------------

3.2.example

文件操作:

with open(r'somefileName') as somefile:

    for line in somefile:

        print line

        # ...more code

 

try/finally 操作文件

somefile = open(r'somefileName')

try:

    for line in somefile:

        print line

        # ...more code

finally:

    somefile.close()

-------------------------------------------------------------------------------

定义:

class A(object):

    def __enter__(self):

        print('__enter__()called')

        return self

   

    def print_hello(self):

        print("helloworld!")

 

    def __exit__(self, e_t,e_v, t_b):

        print('__exit__()called')

调用:

with A() as a:    # a为__enter__的返回对象

    a.print_hello()

    print('got instance')

输出:

__enter__() called

hello world!

got instance

__exit__() called

-------------------------------------------------------------------------------

4.自定义上下文管理器contextlib模块

4.1.装饰器 contextmanager

生成器函数被装饰以后,返回的是一个上下文管理器

装饰器contextmanager 使用示例

from contextlib import contextmanager

@contextmanager

def demo():

    print '[Allocateresources]'  # yield 之前的语句在 __enter__() 方法中执行;资源分配

    print 'Code beforeyield-statement executes in __enter__'

    yield '*** contextmanagerdemo ***'#返回值

    print 'Code afteryield-statement executes in __exit__'

    print '[Free resources]'    # yield 之后的语句在 __exit__() 中执行;资源释放

调用:

with demo() as value:

    print 'Assigned Value: %s'% value

输出:

[Allocate resources]

Code beforeyield-statement executes in __enter__

Assigned Value: ***contextmanager demo ***

Code afteryield-statement executes in __exit__

[Free resources]

      

定义:

@contextmanager

def context():

    print('entering the zone')

    try:

        yield

    except Exception as e:

        print('with an error%s'%e)

        raise e

    else:

      print('with no error')

调用:

with context():

    print('----in contextcall------')

输出:

entering the zone

----in contextcall------

with no error

-------------------------------------------------------------------------------

4.2.函数 nested可以将多个上下文管理器组织在一起,避免使用嵌套 with 语句。

with nested(A(), B(), C()) as (X, Y, Z):

     # with-body code here

类似于:

with A() as X:

    with B() as Y:

        with C() as Z:

             # with-body codehere

需要注意:

发生异常后,如果某个上下文管理器的 __exit__() 方法对异常处理返回 False,

则更外层的上下文管理器不会监测到异常。

-------------------------------------------------------------------------------

4.3.上下文管理器closing

适用提供close() 实现的对象如网络连接、数据库连接等,

可以在自定义类时通过接口 close() 来执行所需要的资源“清理”工作。

class closing(object):

    # help doc here

    def __init__(self,thing):

        self.thing = thing

    def __enter__(self):

        return self.thing

    def __exit__(self,*exc_info):

        self.thing.close()

自定义支持 closing 的对象

class ClosingDemo(object):

    def __init__(self):

        self.acquire()

    def acquire(self):

        print 'Acquireresources.'

    def free(self):

        print 'Clean up anyresources acquired.'

    def close(self):

        self.free()

调用:

with closing(ClosingDemo()):

    print 'Using resources'

输出:

Acquire resources.

Using resources

Clean up anyresources acquired.

-------------------------------------------------------------------------------


猜你喜欢

转载自blog.csdn.net/tcy23456/article/details/80956399
今日推荐