python内置模块之上下文管理contextlib


Posted in Python onJune 14, 2022

Python中当我们们打开文本时,通常会是用with语句,with语句允许我们非常方便的使用资源,而不必担心资源没有关闭。

with open('/path/filename', 'r') as f:
    f.read()

然而,并不是只有open()函数返回fp对象才能使用 with 语句。实际上,任何对象,只要正确实现上下文管理,就可以使用with语句。

实现上下文管理是通过 __enter__ 和 __exit__ 这两个方法实现的。例如,下面的class实现了这两个方法:

class Query(object):
 
    def __init__(self, name):
        self.name = name
 
    def __enter__(self):
        print('Begin')
        return self
 
    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            print('Error')
        else:
            print('End')
 
    def query(self):
        print('Query info about %s...' % self.name)

这样我们可以把自己写的资源对象用于 with 语句。

with Query('Bob') as q:
    q.query()

一、@contextmanager

编写 __enter__ 和 __exit__ 仍然很繁琐,因此Python的标准库 contextlib 提供了更简单的写法,上面的代码可以改写为:

from contextlib import contextmanager
 
class Query(object):
 
    def __init__(self, name):
        self.name = name
 
    def query(self):
        print('Query info about %s...' % self.name)
 
@contextmanager
def create_query(name):
    print('Begin')
    q = Query(name)
    yield q
    print('End')

@contextmanager 这个装饰器接受一个 generator,用 yield 语句把 with ... as var 把变量输出去,然后,with 语句就可以正常的工作了:

with create_query('Bob') as q:
    q.query()

很多时候,我们希望在某段代码执行前后自动执行特定代码,也可以用 @contextmanager实现。

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("" % name)
 
with tag("h1"):
    print("hello")
    print("world")

上述代码执行结果:

hello
world
</h1>

代码的执行顺序是:

  • with 语句 首先执行 yield 之前的语句,因此打印出.
  • yield 调用会执行 with 语句内部的所有语句,因此打印出 hello 和 world.
  • 最后执行yield之后的语句,打印出.

二、@closing

如果一个对象没有实现上下文,就不能使用 with 语句,但是可以用 closing() 来把对象变为上下文对象。

from contextlib import closing
from urllib.request import urlopen
 
with closing(urlopen('https://www.python.org')) as page:
    for line in page:
        print(line)

closing 也是一个经过 @contextmanager 装饰的generator

@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()

它的作用就是把任意对象变为上下文对象,并支持 with语句。

到此这篇关于python内置模块之上下文管理contextlib的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 字符串操作方法大全
Mar 11 Python
Python运用于数据分析的简单教程
Mar 27 Python
Python基于sklearn库的分类算法简单应用示例
Jul 09 Python
Python3匿名函数用法示例
Jul 25 Python
Python爬虫之正则表达式基本用法实例分析
Aug 08 Python
Python获取数据库数据并保存在excel表格中的方法
Jun 12 Python
python celery分布式任务队列的使用详解
Jul 08 Python
python中几种自动微分库解析
Aug 29 Python
Python基于QQ邮箱实现SSL发送
Apr 26 Python
Django视图、传参和forms验证操作
Jul 15 Python
Python大批量搜索引擎图像爬虫工具详解
Nov 16 Python
python中温度单位转换的实例方法
Dec 27 Python
Python时间操作之pytz模块使用详解
Django框架之路由用法
Jun 10 #Python
深入理解pytorch库的dockerfile
Jun 10 #Python
如何利用python实现列表嵌套字典取值
Jun 10 #Python
python中filter,map,reduce的作用
Jun 10 #Python
Django框架中模型的用法
Jun 10 #Python
Django框架中视图的用法
Jun 10 #Python
You might like
利用js调用后台php进行数据处理原码
2006/10/09 PHP
php set_time_limit()函数的使用详解
2013/06/05 PHP
PHP中的类型约束介绍
2015/05/11 PHP
PHP钩子实现方法解析
2019/05/21 PHP
基于php+MySql实现学生信息管理系统实例
2020/08/04 PHP
Git命令之分支详解
2021/03/02 PHP
JavaScript Event学习第八章 事件的顺序
2010/02/07 Javascript
Array.prototype.slice 使用扩展
2010/06/09 Javascript
JavaScript 小型打飞机游戏实现原理说明
2010/10/28 Javascript
extjs之去除s.gif的影响
2010/12/25 Javascript
jQuery 获取兄弟元素的几种不错方法
2014/05/23 Javascript
js使用removeChild方法动态删除div元素
2014/08/01 Javascript
全面解析Bootstrap表单使用方法(表单按钮)
2015/11/24 Javascript
Bootstrap基本插件学习笔记之按钮(21)
2016/12/08 Javascript
JS和canvas实现俄罗斯方块
2017/03/14 Javascript
vue.js轮播图组件使用方法详解
2018/07/03 Javascript
微信小程序实现之手势锁功能实例代码
2018/07/19 Javascript
Bootstrap模态对话框用法简单示例
2018/08/31 Javascript
微信小程序常见页面跳转操作简单示例
2019/05/01 Javascript
Nuxt 项目性能优化调研分析
2020/11/07 Javascript
[01:00]选手抵达华西村 整装待发备战2016国际邀请赛中国区预选赛
2016/06/25 DOTA
在Python中处理XML的教程
2015/04/29 Python
Python实现信用卡系统(支持购物、转账、存取钱)
2016/06/24 Python
解决pycharm的Python console不能调试当前程序的问题
2019/01/20 Python
Pytorch中膨胀卷积的用法详解
2020/01/07 Python
Python替换NumPy数组中大于某个值的所有元素实例
2020/06/08 Python
Python获取浏览器窗口句柄过程解析
2020/07/25 Python
python+selenium实现12306模拟登录的步骤
2021/01/21 Python
商务英语专业应届毕业生求职信
2013/10/28 职场文书
社区健康教育实施方案
2014/03/18 职场文书
基本公共卫生服务健康教育工作方案
2014/05/22 职场文书
大学生万能检讨书范例
2014/10/04 职场文书
2016年村党支部公开承诺书
2016/03/24 职场文书
《烈火英雄》观后感:致敬和平时代的英雄
2019/11/11 职场文书
python字符串的多行输出的实例详解
2021/06/08 Python
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA