十六、Python 上下文管理 Context Manager

要使用 with 语句,首先要明白上下文管理器这一概念。有了上下文管理器,with 语句才能工作。下面是一组与上下文管理器和with 语句有关的概念。

上下文管理协议(Context Management Protocol):包含方法 __enter__() 和 __exit__(),支持该协议的对象要实现这两个方法。

上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__() 和 __exit__()
方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,

也可以通过直接调用其方法来使用。运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的
__enter__() 和

__exit__() 方法实现,__enter__() 方法在语句体执行之前进入运行时上下文,__exit__() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。上下文表达式(Context
Expression):with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。

语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管

理器的 __enter__() 方法,执行完语句体之后会执行 __exit__() 方法。

#-----*-coding:utf-8-*-----
"""
Python’s with statement was first introduced five years ago,
in Python 2.5. It’s handy when you have two related operations which you’d like to execute as a pair,
 with a block of code in between. The classic example is opening a file, manipulating the file, then closing it:

with open('output.txt', 'w') as f:
    f.write('Hi there!')
The above with statement will automatically close the file after the nested block of code.
(Continue reading to see exactly how the close occurs.)
The advantage of using a with statement is that it is guaranteed to close the file no matter how the nested block exits.
If an exception occurs before the end of the block,
it will close the file before the exception is caught by an outer exception handler.
 If the nested block were to contain a return statement, or a continue or break statement,
  the with statement would automatically close the file in those cases, too.
"""

f = open("numbers.txt", "w")
f.write("hello")
f.close()

with open("numbers.txt", "w") as f:
    f.write("hello")

f = open("numbers.txt")
print dir(f)

import os

class chdir:

    def __init__(self, dir):
        self.dir = dir
        print "__init__"

    def __enter__(self):
        print "__enter__"
        self.olddir = os.getcwd()
        os.chdir(self.dir)
        return self

    def __exit__(self, *a):
        print "__exit__"
        os.chdir(self.olddir)

print os.getcwd()
print "before with"
with chdir("/tmp") as x:
    print os.getcwd()
print "after with"
print os.getcwd()

'''
Problem Write a context manager capture_output to capture stdout inside a with block.

with capture_output() as buf:
    print "hello"

out = buf.getvalue()
print "captured", repr(out)

Hint: See StringIO.StringIO and sys.stdout.

Lets try to understand how to capture output without context managers.
'''

import sys
from StringIO import StringIO

oldstdout = sys.stdout
buf = StringIO()
sys.stdout = buf
print "hello"
print "world"
sys.stdout = oldstdout
print "Captured", repr(buf.getvalue())

class capture_output:
	def __init__(self):
		self.buf=StringIO()

	def __enter__(self):
		self.oldstdout=sys.stdout
		sys.stdout=self.buf
		return self.buf

	def __exit__(self,type,exc,traceback):
		sys.stdout=self.oldstdout

capture_output()
print "hello"

result:

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
/Users/macbook/Proj/practise
before with
__init__
__enter__
/private/tmp
__exit__
after with
/Users/macbook/Proj/practise
Captured 'hello\nworld\n'
hello
[Finished in 0.1s]
时间: 2024-10-09 10:23:37

十六、Python 上下文管理 Context Manager的相关文章

十六. 面向对象上下文管理协议

一. __enter__和__exit__ 我们知道在操作文件对象的时候可以这么写 1 with open('a.txt') as f: 2 '代码块' 上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法 # 上下文管理协议 class Open: def __init__(self,name): self.name=name def __enter__(self): print('出现with语句,对象的__

python上下文管理器及with语句

with语句支持在一个叫上下文管理器的对象的控制下执行一系列语句,语法大概如下: with context as var: statements 其中的context必须是个上下文管理器,它实现了两个方法__enter__,__exit__. 1.需求是怎么产生的 在正常的管理各种系统资源(文件.锁定和连接),在涉及到异常时通常是个棘手的问题.异常很可能导致控制流跳过负责释放关键资源的语句. 看一段简单的文件写入代码: filename = 'my_file.txt' f = open(file

Objective-C(十六、内存管理,自动释放池,ARC,强指针,弱指针,方法族)——iOS开发基础

结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 十六.内存管理相关知识(二) 1.autorelease,自动释放机制 - (instancetype)autorelease; (1)自动释放池的创建 iOS5.0之前 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //进行一系列操作 //此处不可以使用

十六、变更管理; 十七、信息系统安全管理; 十八、项目风险管理

十六.变更管理 1.  变更的工作程序 (1).提出与接受变更申请 (2).对变更的初审 (3).变更方案论证 (4).项目变更控制委员会审查 (5).发出变更通知并开始实施 (6).变更实施的监控 (7).变更效果的评估 (8).判断发生变更后的项目是否已纳入正常轨道 2.  变更初审的4条内容 (1).对变更提出方施加影响,确认变更的必要性,确保变更是有价值的 (2).格式校验,完整性较验,确保评估所需信息准备充分 (3).在干系人间就提出供评估的变更信息达成共识 (4).变更初审的常见方式

linux基础-第十六单元 yum管理RPM包

第十六单元 yum管理RPM包 yum的功能 本地yum配置 光盘挂载和镜像挂载 本地yum配置 网络yum配置 网络yum配置 Yum命令的使用 使用yum安装软件 使用yum删除软件 安装组件 删除组件 清除缓存 查询 课后作业 [本节内容]1. yum的功能:yum是Yellow dog Updater, Modified的缩写,目的就是为了解决RPM的依赖关系的问题,方便使用者进行软件的安装.升级等等工作.2. 掌握光盘挂载和镜像挂载a) 光盘挂载mount /dev/sr0 挂载点或者

Python上下文管理器(context manager)

上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围.一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存).它的语法形式是with...as... # with context manager with open("new.txt", "w") as f: print(f.closed) f.write("Hello World!") print(f.close

Python上下文管理器(Context managers)

上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还要在它们中间放置一段代码.上下文管理器就是专门让你做这种事情的.举个例子: with open('some_file', 'w') as opened_file: opened_file.write('Hola!') 上面这段代码打开了一个文件,往里面写入了一些数据,然后关闭该文件.如果在往文件写数

流畅的python第十五章上下文管理器和else块学习记录

with 语句和上下文管理器for.while 和 try 语句的 else 子句 with 语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文.这么做能避免错误并减少样板代码,因此 API 更安全,而且更易于使用.除了自动关闭文件之外,with 块还有很多用途 else 子句不仅能在 if 语句中使用,还能在 for.while 和 try 语句中使用 for 仅当 for 循环运行完毕时(即 for 循环没有被 break 语句中止)才运行 else 块.while 仅

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

http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from __future__ import with_statement 导入后才可以使用),从 2.6 版本开始缺省可用(参考 What's new in Python 2.6? 中 with 语句相关部分介绍).with 语句适用于对资源进行访问的场合,确保不管使用过程