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("</%s>" % name) with tag("h1"):
print("hello")
print("world")

  上述代码执行结果:

<h1>
hello
world
</h1>

  代码的执行顺序是:

  1. with 语句 首先执行 yield 之前的语句,因此打印出 <h1>.
  2. yield 调用会执行 with 语句内部的所有语句,因此打印出 hello 和 world.
  3. 最后执行yield之后的语句,打印出 </h1>.

@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语句。

本文引用于廖雪峰的博客

Python3之 contextlib的更多相关文章

  1. (转)contextlib — 上下文管理器工具

    原文:https://pythoncaff.com/docs/pymotw/contextlib-context-manager-tool/95 这是一篇社区协同翻译的文章,你可以点击右边区块信息里的 ...

  2. Python 上下文管理器模块--contextlib

    在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...

  3. Python标准模块--ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  4. python 安装第三方库,超时报错--Read timed out.

    Traceback (most recent call last): File "/home/xiaoduc/.pyenv/versions/3.5.0/lib/python3.5/site ...

  5. tensorflow由于未初始化变量所导致的错误

     版权声明:本文为博主原创文章,如需转载请注明出处,谢谢. https://blog.csdn.net/qq_38542085/article/details/78742295 初始代码 import ...

  6. python安装pandas模块

    直接安装时报错了 localhost:~ ligaijiang$ pip3 install pandas Collecting pandas Downloading https://files.pyt ...

  7. python-性能测试

    目录: 1.timeit 1.1 在命令后调用timeit 1.2 在代码中使用 1.3 创建计时器实例,通过autorange获得循环次数 1.4 Wall时间和CPU时间 2.profile和cP ...

  8. celery 4.1下报kombu.exceptions.EncodeError: Object of type 'bytes' is not JSON serializable 处理方式

    #python代码如下 from celery import Celeryimport subprocess app = Celery('tasks', broker='redis://localho ...

  9. VS code MacOS 环境搭建

    环境:MacBook Pro 参考博客 为了动手开发AI代码,我需要安装一个VS code. 开始我以为是安装visual studio呢.我装过visual studio2017. VS code是 ...

随机推荐

  1. 关于java是值传递还是引用传递

    一.概念 实际上对这两种传递方式,知乎上有个回答说得很好: 值传递和引用传递,属于函数调用时参数的求值策略(Evaluation Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递 ...

  2. qy Undefied index报错

    目测是不支持如下写法 $value['status'] = $map[$value['status']];

  3. Greeplum 系列(四) 实战

    Greeplum 系列(四) 实战 表结构 (1) 拉链表结构 create table public.member_fatdt0 ( member_id varchar(64), phoneno v ...

  4. JMS 之 Active MQ的安全机制

    一.认证 认证(Authentication):验证某个实体或者用户是否有权限访问受保护资源. MQ提供两种插件用于权限认证:(一).Simple authentication plug-in:直接把 ...

  5. Web测试实践--Rec 2

    累计完成任务情况: 阶段内容 参与人 进行用户调研 小熊 开会学习作业要求,取得共识 全体 注: 1."阶段内容"划斜线表示完成.2.采用倒序. 具体情况: 小熊主要围绕以下几方面 ...

  6. html传参数 js工具类

    var QueryUtils = { GetQueryString: function (name) { var reg = new RegExp("(^|&)" + na ...

  7. ubuntu-server部署php+mysql运行环境

    1.apt-get install git php5 mysql-server apache2 phpmyadmin 2.sudo ln -s /usr/share/phpmyadmin /var/w ...

  8. 马尔可夫决策过程MDP

    1. 马尔可夫模型的几类子模型 马尔科夫链(Markov Chain),了解机器学习的也都知道隐马尔可夫模型(Hidden Markov Model,HMM).它们具有的一个共同性质就是马尔可夫性(无 ...

  9. 敏捷软件开发:原则、模式与实践——第9章 OCP:开放-封闭原则

    第9章 OCP:开放-封闭原则 软件实体(类.模块.函数等)应该是可以扩展的,但是不可修改. 9.1 OCP概述 遵循开放-封闭原则设计出的模块具有两个主要特征: (1)对于扩展是开放的(open f ...

  10. codeforces 914E Palindromes in a Tree(点分治)

    You are given a tree (a connected acyclic undirected graph) of n vertices. Vertices are numbered fro ...