写点什么

浅淡 python 中 with 的用法,上下文管理器

用户头像
极客新人
关注
发布于: 2021 年 03 月 07 日

上下文管理器


任何实现了 enter() 和 exit() 方法的对象都可称之为上下文管理器,上下文管理器对象可以使用 with 关键字。显然,文件(file)对象也实现了上下文管理器。


那么文件对象是如何实现这两个方法的呢?我们可以模拟实现一个自己的文件类,让该类实现 enter() 和 exit() 方法。


class File():
def __init__(self, filename, mode): self.filename = filename self.mode = mode
def __enter__(self): print("entering") self.f = open(self.filename, self.mode) return self.f
def __exit__(self, *args): print("will exit") self.f.close()
复制代码


enter() 方法返回资源对象,这里就是你将要打开的那个文件对象,exit() 方法处理一些清除工作。


因为 File 类实现了上下文管理器,现在就可以使用 with 语句了。


with File('out.txt', 'w') as f:    print("writing")    f.write('hello, python')
复制代码


这样,你就无需显示地调用 close 方法了,由系统自动去调用,哪怕中间遇到异常 close 方法也会被调用。


实现上下文管理器的另外方式


Python 还提供了一个 contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。通过 yield 将函数分割成两部分,yield 之前的语句在 enter 方法中执行,yield 之后的语句在 exit 方法中执行。紧跟在 yield 后面的值是函数的返回值。


from contextlib import contextmanager
@contextmanagerdef my_open(path, mode): f = open(path, mode) yield f f.close()
复制代码


调用


with my_open('out.txt', 'w') as f:    f.write("hello , the simplest context manager")
复制代码


总结


Python 提供了 with 语法用于简化资源操作的后续清除操作,是 try/finally 的替代方法,实现原理建立在上下文管理器之上。此外,Python 还提供了一个 contextmanager 装饰器,更进一步简化上下管理器的实现方式。


拓展文章:


1.浅淡 python 中 with 的用法,上下文管理器


https://www.cnblogs.com/huchong/p/8268765.html


(1) 当 with 遇到上下文管理器,就会在执行语句体之前,先执行上下文管理器的 enter 方法,然后再执行语句体,执行完语句体后,最后执行 exit 方法


(2) 使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄


(3)调用上下文管理器的 enter 方法时;如果使用了 as 子句,则将 enter() 方法的返回值赋值给 as 子句中的目标


with 上下文管理器  as  target:   代码语句体
复制代码


with 后面必须跟一个上下文管理器,如果使用了 as,则是把上下文管理器的 __enter__() 方法的返回值赋值给 target,target 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)


(4) 出现异常时,如果 __exit__ 返回 False(默认不写返回值时,即为 False),则会重新抛出异常,让 with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理


(5)with 只能配合上下文管理器使用,常见的上下文管理器有


filedecimal.Contextthread.LockTypethreading.Lockthreading.RLockthreading.Conditionthreading.Semaphorethreading.BoundedSemaphore
复制代码


2. with 上下文管理器


https://www.cnblogs.com/menkeyi/p/7130978.html


contextlib 模块


contextlib 模块提供了 3 个对象:装饰器 contextmanager、函数 nested 和上下文管理器 closing。使用这些对象,可以对已有的生成器函数或者对象进行包装,加入对上下文管理协议的支持,避免了专门编写上下文管理器来支持 with 语句。


装饰器 contextmanager


contextmanager 用于对生成器函数进行装饰,生成器函数被装饰以后,返回的是一个上下文管理器,其 enter() 和 exit() 方法由 contextmanager 负责提供,而不再是之前的迭代子。被装饰的生成器函数只能产生一个值,否则会导致异常 RuntimeError;产生的值会赋值给 as 子句中的 target,如果使用了 as 子句的话。


3.上下文管理器


https://blog.csdn.net/weixin_38853600/article/details/82887907

发布于: 2021 年 03 月 07 日阅读数: 18
用户头像

极客新人

关注

还未添加个人签名 2018.11.24 加入

还未添加个人简介

评论

发布
暂无评论
浅淡python中with的用法,上下文管理器