在Python中,读写文件这样的资源要特别注意,必须在使用完毕后正确关闭它们。正确关闭文件资源的一个方法是使用try...finally

try:
f = open('/path/to/file', 'r')
f.read()
finally:
if f:
f.close()

try...finally非常繁琐。Python的with语句允许我们非常方便地使用资源,而不必担心资源没有关闭,所以上面的代码可以简化为:

with open('/path/to/file', '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这个decorator接受一个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语句内部的所有语句,因此打印出helloworld
  3. 最后执行yield之后的语句,打印出</h1>

因此,@contextmanager让我们通过编写generator来简化上下文管理。

@closing

如果一个对象没有实现上下文,我们就不能把它用于with语句。这个时候,可以用closing()来把该对象变为上下文对象。例如,用with语句使用urlopen()

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,这个generator编写起来其实非常简单:

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

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

@contextlib还有一些其他decorator,便于我们编写更简洁的代码。

contextlib 上下文管理器的更多相关文章

  1. python contextlib 上下文管理器

    1.with操作符 在python中读写文件,可能需要这样的代码 try-finally读写文件 file_text = None try: file_text = open('./text', 'r ...

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

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

  3. 【Python】 上下文管理器和contextlib

    上下文管理器 一直对python中的上下文管理比较迷惑,趁着今天研究SQLAlchemy顺便看了一下,感觉稍微清楚了一点.http://www.cnblogs.com/chenny7/p/421344 ...

  4. python上下文管理器ContextLib及with语句

    http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...

  5. python 上下文管理器contextlib.ContextManager

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

  6. Python中的上下文管理器(contextlib模块)

    上下文管理器的任务是:代码块执行前准备,代码块执行后收拾 1 如何使用上下文管理器: 打开一个文件,并写入"hello world" filename="my.txt&q ...

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

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

  8. contextlib:上下文管理器工具

    介绍 contextlib模块包含的工具可以用于处理上下文管理器和with语句 上下文管理器API ''' 上下文管理器(context manager)负责管理一个代码块中的资源,会在进入代码块时创 ...

  9. python2.7高级编程 笔记一(Python中的with语句与上下文管理器学习总结)

    0.关于上下文管理器上下文管理器是可以在with语句中使用,拥有__enter__和__exit__方法的对象. with manager as var: do_something(var) 相当于以 ...

随机推荐

  1. Linux:常用命令【转载】

    转载于:https://www.cnblogs.com/yjd_hycf_space/p/7730690.html 系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架 ...

  2. 4.高级js--(面向对象js)_2

    1.创建对象的三种方式: l第一种构造法:new  Object var a = new Object(); a.x = 1, a.y = 2; l第二种构造法:对象直接量 var b = { x : ...

  3. leetcode701

    class Solution: def insertIntoBST(self, root, val): """ Time: O(log(n)) [average case ...

  4. 源码编译php5.4 ./configure参数

    ./configure \--prefix=/usr/local/php/5.4 \--with-config-file-path=/usr/local/php/5.4/etc \--with-con ...

  5. 深度学习原理与框架-Tensorflow基本操作-Tensorflow中的变量

    1.tf.Variable([[1, 2]])  # 创建一个变量 参数说明:[[1, 2]] 表示输入的数据,为一行二列的数据 2.tf.global_variables_initializer() ...

  6. spring boot 的常用注解

    SpringBoot用于简化Spring应用的搭建,开发及部署:该框架采用注解的方式进行配置可以很方便的构建Spring应用. 1. @SpringBootApplication @SpringBoo ...

  7. jquery-menu-aim插件实现二级导航

    jquery-menu-aim插件是实现二级导航亚马逊式三角滑动的强力工具,它在性能上极佳,快速滑动,基本无延迟效果,源码位置见对应作者的github,接下来附上样例代码: $(function () ...

  8. HTML页面禁用Enter键自动提交表单

    今天在开发页面时,遇到一个小BUG,,如下图 在页面的文本框获取焦点之后,再按键盘上的Enter键,页面form就会自动提交.如下是页面禁止Enter自动提交代码: document.onkeydow ...

  9. Lazarus中Windows单元问题

    在程序中加入Windows 单元后,经常会使一些过程和函数莫名其妙的报错,这是因为Windows单元很多函数,过程 与sysutils 单元重名 ,所以一般要把windows 引用放在 sysutil ...

  10. C++复习:异常

    异常处理机制专题 前言 1)异常是一种程序控制机制,与函数机制独立和互补     函数是一种以栈结构展开的上下函数衔接的程序控制系统,异常是另一种控制结构,它依附于栈结构,却可以同时设置多个异常类型作 ...