Python之with语句
Python之with语句
在Python中,我们在打开文件的时候,为了代码的健壮性,通常要考虑一些异常情况,比如:
try:
ccfile = open('/path/data')
content = ccfile.readlines()
ccfile.close() except IOError:
log.write('no data read\n')
我们将真正干活的代码扔到try语句块中,如果文件操作出现异常,则写一条错误日志;
考虑一种情况,如果文件打开成功,但readlines()调用失败,异常处理会立即跳转到except处执行,这样文件关闭就没有机会被执行到了。
一种解决办法就是将close()语句放到finally子句中去,finally的特点是不管有无异常,都会被执行到。
try:
try:
ccfile = open('/path/data')
content = ccfile.readlines() except IOError:
log.write('no data read\n') finally
ccfile.close()
finally的另一种可选的风格:
try:
try:
ccfile = open('/path/data')
content = ccfile.readlines() finally IOError:
ccfile.close() except IOError:
log.write('no data read\n')
如上所述的标准化的 try-except和try-finally 的用法是保证资源的分配和回收,比如文件(数据、日志、数据库等等)、线程资源、数据库连接等,但它们书写起来却不够优雅。with语句的目的在于从流程图中把try、except、 finally关键字和资源分配、释放相关代码统统去掉,
with处理文件操作的一个实例:
with open('/etc/passwd') as f:
for line in f:
print(line)
这段代码的作用:打开一个文件,如果一切正常,把文件对象赋值给f,然后用迭代器遍历文件中每一行,当完成时,关闭文件;而无论在这段代码的任何地方,如果发生异常,此时文件仍会被关闭。
with看起来如此简单,但是其背后还有一些工作要做,因为你不能对Python的任意符号使用with语句,它仅能工作于支持上下文管理协议(context management protocol)的对象。也就是说,只有内建了“上下文管理”的对象可以和with一起工作,目前支持该协议的对象有:
- file
- decimal.Context
- thread.LockType
- threading.Lock
- threading.RLock
- threading.Condition
- threading.Semaphore
- threading.BoundedSemaphore
现在来看with的语法:
with context_expr as var:
with_suite
当with语句执行时,便执行上下文表达式(context_expr)来获得一个上下文管理器,上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
一旦获得了上下文对象,就会调用它的__enter__()方法,将完成with语句块执行前的所有准备工作,如果with语句后面跟了as语句,则用__enter__()方法的返回值来赋值;
当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法,__exit__()方法有3个参数,如果with语句正常结束,三个参数全部都是 None;如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。
因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法基本是干的需要分配和释放资源的低层次工作,比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等。
现在,我们可以在自定义类里面创建__enter__()和__exit__()方法,这样就可以配合with语句创建类实例了:
class A:
def __enter__(self):
print '__enter__() called' def __exit__(self, e_t, e_v, t_b):
print '__exit__() called' with A() as a:
print('got instance')
可以看到输出为:
__enter__() called
got instance
__exit__() called
另外python库中还有一个模块contextlib,使你不用构造含有__enter__, __exit__的类就可以使用with:
from __future__ import with_statement
from contextlib import contextmanager @contextmanager
def context():
print 'entering the zone'
try:
yield
except Exception, e:
print 'with an error %s'%e
raise e
else:
print 'with no error' with context():
print '----in context call------'
参考文档:
http://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/
Python之with语句的更多相关文章
- 理解python的with语句
Python’s with statement provides a very convenient way of dealing with the situation where you have ...
- (Python )控制流语句if、for、while
这一节,我们将学习Python的控制流语句,主要包括if.for.while.break.continue 和pass语句 1. If语句 if语句也许是我们最熟悉的语句.其使用方法如下: x=inp ...
- Python的with语句
写过多线程程序的人肯定对各种锁很熟悉,尤其是下面这种代码 def lock_usage: lock.Lock() if(...) : lock.Unlock() return lock.Unlock( ...
- Python学习教程(learning Python)--3.3.4 Python的if-elif-else语句
Python的if-elif-else语句用于多种条件判断后选择某个语句块执行.该语句可以利用一系列条件表达式进行检查,并在某个表达式为真的情况下执行相应的代码.需要注意的是,虽然if/elif/el ...
- 转: 理解Python的With语句
Python’s with statement provides a very convenient way of dealing with the situation where you have ...
- python的with语句,超级强大
With语句是什么? 有一些任务,可能事先需要设置,事后做清理工作.对于这种场景,Python的with语句提供了一种非常方便的处理方式.一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取 ...
- 简单探讨python中的语句和语法
python程序结构 python"一切皆对象",这是接触python听到最多的总结了.在python中最基层的单位应该就是对象了,对象需要靠表达式建立处理,而表达式往往存在于语句 ...
- python assert 断言语句的作用
python assert 断言语句的作用 assert语句的应用场景 使用assert语句是一个很好的习惯. 我们在编写代码的时候, 不知道程序会在什么时候崩溃, 与其让它在深度运行时崩溃, 不如预 ...
- Python: 没有switch-case语句
初学Python语言,竟然很久才发现Python没有switch-case语句 官方的解释说,“用if... elif... elif... else序列很容易来实现 switch / case 语句 ...
随机推荐
- JS 正则表达式中的特殊字符
正则表达式中的特殊字符 字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个 ...
- win7安装nodejs
刚刚在网上看到Cheerio,为服务器特别定制的,快速.灵活.实施的jQuery核心实现,适合各种Web爬虫程序. 看了下,cheerio 是nodejs的抓取页面模块 于是决定先学习下nodejs了 ...
- Casually have a look
1. 用红盘子吃饭能助你减肥.教授告诉我们:“红色是一种原始的危险信号,它同时也会使盘中的食物看上去不那么诱人,所以你也会吃得更少.” 2. 要减肥请关电视.教授说:“如果你需要减肥,请在吃饭时把电视 ...
- 【bzoj1503】 NOI2004—郁闷的出纳员
http://www.lydsy.com/JudgeOnline/problem.php?id=1503 (题目链接) 题意 要求维护4种操作:插入一个数,将所有数加上k,将所有数减去k,删去数值小于 ...
- CCTray配置如何添加远程服务器
前提: Windows防火墙必须开通的TCP端口 或者直接把防火墙关闭(不建议) 或者直接在防火墙规则增加CCNET的服务进去 总者,只要确保能telnet ip 21234能通即可 建议全部软件都装 ...
- Spring mvc web 配置
Spring Framework本身没有Web功能, Spring MVC使用WebApplicationContext类扩展ApplicationContext ,使得拥有web功能.那么,Spri ...
- Newtonsoft.Json动态过滤属性
Newtonsoft.Json动态过滤属性 接口写的多了,会发现很多的问题.同一个dto,不同的action返回的字段个数不一样.往往开发人员因为懒或者各种原因一股脑的全返回,会浪费很多流量且用户体验 ...
- 电脑技巧:Win8/Win10无法打开这个应用|无法使用内置管理员账户的完美解决方法
现在装win10系统的同伴越来越多了,相比于win7,win10在某些设置方面也有些变化,比如我们在使用win8或者win10时,会碰到如图所示的对话框: Windows10/Windows8无法使用 ...
- 远程连接实验室的VPN
Windows 7 (win8类似)的用户请按以下步骤进行操作:1.点击“开始”菜单,然后点击“控制面板”,然后点击“查看网络和任务”.2.点击“设置新连接或网络”.3.点击“连接到工作区”,然后点击 ...
- 安装scikit-learn过程记录
环境:Windows 10 X64企业版. 安装python2.7: 官网下载python-2.7.12.amd64.msi安装文件,过程不赘述.安装完成后在PATH环境变量中加入%PYTHON_HO ...