• python上下文管理器


    1.what AND demo

    我们希望把一些操作放到一个代码块中,这样在代码块中执行时就可以保持在某种运行状态,而当离开该代码块时就执行另一个操作,结束当前状态;所以,简单来说,上下文管理器的目的就是规定对象的使用范围,如果超出范围就采取“处理”。

    with 语句内置上下文管理工具。

    with open("test/test.txt","w") as f:
      f.write("hello")

    不使用上下文管理工具:

    f = open("hl.txt", "w")
    print(f.closed)  #运行到这里,会打印出False,因为没有关闭
    f.write("Hello,context manager!")
    f.close()
    print(f.closed)  #这里才会打印出True,表示文件关闭

    如果这段代码根本执行不到f.close()这一句,就出现问题,这样就永远执行不到f.close()这一句,文件就永远不会被关闭。

    可以用try…finally语句。

    2.how自定义一个上下文管理器

    上下文管理协议(Context Management Protocol):包含方法 __enter__() 和 __exit__(),支持该协议的对象要实现这两个方法。
    上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__() 和 __exit__() 方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。
    运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的 __enter__() 和__exit__() 方法实现,
    __enter__() 方法在语句体执行之前进入运行时上下文,
    __exit__() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。
    上下文表达式(Context Expression):with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。

    class MyMananger:
        # __enter__ 返回的对象会被with语句中as后的变量接受
        def __enter__(self):
            print('connect to resource')
            return self
    
        def __exit__(self, exc_type, exc_value, tb):
            print('close resource conection')
    
        def query(self):
            print('query data')
    with MyManager() as r:
        r.query()

    结果:

    connect to resource
    query data
    close resource conection

    3.contextlib中的装饰器contextmanager

    demo1:

    from contextlib import contextmanager
    class Mydoit:
        def doit(self):
            print('just do it')
    
    @contextmanager
    def make_contextmanager():
        print('start to connect')
        yield Mydoit()
        print('end connect')
        pass

    被装饰器装饰的函数分为三部分: 
    with语句中的代码块执行前执行函数中yield之前代码 
    yield返回的内容复制给as之后的变量 
    with代码块执行完毕后执行函数中yield之后的代码

    with Mydoit() as r:
         r.doit()

    结果是:

    start to connect
    just do it
    end connect

     demo2:

    #通过一个 yield 分为2个部分.
    #yield 前的代码 相当于 __enter__ , yield 后的代码相当于 __exit__
    #而 yiled 产出的值 相当于  as 的变量上.
    
    import contextlib
     
    #装饰一下 
    @contextlib.contextmanager
    def open_file(filepath):
     
        #相当于 __enter__
        print("准备打开")
        fileObject = open(filepath,'r')
        print("打开结束 , 准备yield")
     
        # fileObject 将赋值 给  as 后的变量
        yield fileObject
     
     
        # 下面的代码相当于 __exit__
        print("准备close")
        fileObject.close()
        print("close完成")
     
     
     
    with open_file("D:dex.txt") as fd:
        print("with 块进入了")
        time.sleep(3)
        print("完成操作")

    demo3:

    from contextlib import contextmanager
     
    @contextmanager
    def example():
        l = [1,2,3,4]
        print('start')
        try:
            # raise Exception('test')
            yield l
        finally:
            print('end')
            
    with example() as msg:
        try:
            for i in msg:
                print(i)
        except:
            print(e.message)
                
    start
    1
    2
    3
    4
    end
  • 相关阅读:
    Linux/Unix time时间戳的处理转换函数
    linux下socket编程:区分close()与shutdown()
    数组注意事项
    grep v XXXXX
    [转]计算机读研的取向
    tail f 文件名
    字符串与整数、浮点数、无符号整数之间的转换常用函数
    Linux共享库(动态库)与进程之间全局变量是无法共享的
    静态库、共享库、动态库的创建和使用
    请教bcopy和memcpy的区别
  • 原文地址:https://www.cnblogs.com/wqbin/p/10693602.html
Copyright © 2020-2023  润新知