contextlib 搭配 yield 简化上下文管理器

高级编程技巧 学习笔记

一、Python 中的 with 语句


1.1、什么是上下文

  • python 中的上下文,指的就是代码所执行的环境状态,或者运行的场景。

  • python 上下文管理器规定了某个对象的使用范围,当进入或者离开了使用范围,会有相应的操作,多用于资源的分配和释放上,即在开始时分配资源,结束时释放资源。

  • 如文件的读写,在读写前,需要先打开文件,在读写完成后,需要关闭文件。再如数据库的操作,在操作前,需要先连接数据库,结束后,需要释放连接等。

1.2、使用 try … except … 实现上下文(以读写文件为例)

try:
    f = open('test.txt', 'w')
    # print("code")
    raise KeyError
except KeyError as e:
    print('Key Error')
    f.close()
except IndexError as e:
    print('IndexError')
    f.close()
except Exception as e:
    print(e)
    f.close()
finally:
    # 不管有没有异常都会运行
    print('end')
    f.close()

代码冗余,且容易漏写(忘记关闭,没有释放资源)。

1.3、定义类实现上下文

  • 必须有 __enter__(self) 方法获取资源

  • 必须有 __exit__(self, exc_type, exc_val, exc_tb) 方法释放资源

  • 有错误时才能看到 __exit__ 方法的几个参数

class Sample():
    # 实例化后调用方法前
    def __enter__(self):
        print("start")
        return self

    def demo(self):
        print("this is demo")

    def demo2(self):
        print("this is demo2")

    # 释放资源的时候(结束程序时)
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exc_type: ",exc_type)                # 异常类  <class 'AttributeError'>
        print("exc_val: ",exc_val)                  # 异常值  'Sample' object has no attribute 'dems'
        print("exc_tb: ",exc_tb)                    # 跟踪信息 <traceback object at 0x000001AC339178C8>
        print("end")


with Sample() as sample:
    sample.demo()
    sample.demo2()
    # sample.dems()

比较麻烦,一定要定义 __enter____exit__ 方法。

1.4、使用 contextlib 与 yield 实现上下文

import contextlib

@contextlib.contextmanager
def file_open(filename):
    print("file open")
    # yield {}                			# yield 的返回值类型无所谓
    yield []                  			# 不能用 return, return 会结束 yield 不会结束
    print("file close")

with file_open("demo.txt") as f:
    print("66666")
    print("88888")
发布了85 篇原创文章 · 获赞 0 · 访问量 1234

猜你喜欢

转载自blog.csdn.net/qq_43621629/article/details/104066634
今日推荐