打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Python上下文管理器
with语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文。
比如在打开文件时通常都会使用with语句:
with open("a.txt") as f:
f.read()
with块执行完后会自动关闭文件。
Python上下文管理器对象存在的目的就是管理with语句。

实现一个上下文管理器

上下文管理器协议包含__enter____exit__两个方法,所以要实现一个上下文管理器,就得实现这两个方法,比如:
class LookingGlass:

def __enter__(self):
import sys
self.original_write = sys.stdout.write
sys.stdout.write = self.reverse_write
return 'JABBERWOCKY'

def reverse_write(self, text):
self.original_write(text[::-1])

def __exit__(self, exc_type, exc_value, traceback):
import sys
sys.stdout.write = self.original_write
if exc_type is ZeroDivisionError:
print('Please DO NOT divide by zero!')
return True
  • __enter__是上下文管理器的入口,在with语句开始运行时调用。

  • __exit__是上下文管理器的出口,在with语句运行结束后调用。

上下文管理器对象是在执行with后面的表达式得到的:
with LookingGlass() as what:
print(what)
as子句是可选的,在as执行前就已经得到了上下文管理器对象,在as执行时实际就已经调用__enter__了。

把生成器变为上下文管理器

使用@contextmanager装饰器能减少创建上下文管理器的样板代码量,只需要实现一个有yield语句的生成器,生成想让__enter__方法返回的值。
示例:
import contextlib


@contextlib.contextmanager
def looking_glass():
import sys
original_write = sys.stdout.write

def reverse_write(text):
original_write(text[::-1])

sys.stdout.write = reverse_write
msg = ''
try:
yield 'JABBERWOCKY'
except ZeroDivisionError:
msg = 'Please DO NOT divide by zero!'
finally:
sys.stdout.write = original_write
if msg:
print(msg)
yield语句的作用是:
  • 在yield语句前面的代码在with块开始时执行,相当于__enter__

  • 在yield语句后面的代码在with块结束时执行,相当于__exit__

注意这里的yield与迭代没有任何关系,这其实引出了Python另一个重要技术点,协程:执行到某一点时暂停,让客户代码运行,直到客户让协程继续做事。下篇文章将展开对Python协程的学习。
参考资料:
《流畅的Python》第15章 上下文管理器和else块
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Python 标准输出 sys.stdout 重定向
Python字体颜色设置
python中stdout是什么意思
Python标准模块
Python进阶系列(十七)
防止Python的stdout被缓存的几种方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服