Python之with语句

在Python中,我们在打开文件的时候,为了代码的健壮性,通常要考虑一些异常情况,比如:

try:

ccfile= open('/path/data')

content=ccfile.readlines()

ccfile.close()exceptIOError:

log.write('no data read\n')

我们将真正干活的代码扔到try语句块中,如果文件操作出现异常,则写一条错误日志;

考虑一种情况,如果文件打开成功,但readlines()调用失败,异常处理会立即跳转到except处执行,这样文件关闭就没有机会被执行到了。

一种解决办法就是将close()语句放到finally子句中去,finally的特点是不管有无异常,都会被执行到。

try:try:

ccfile= open('/path/data')

content=ccfile.readlines()exceptIOError:

log.write('no data read\n')finallyccfile.close()

finally的另一种可选的风格:

try:try:

ccfile= open('/path/data')

content=ccfile.readlines()finallyIOError:

ccfile.close()exceptIOError:

log.write('no data read\n')

如上所述的标准化的 try-except和try-finally 的用法是保证资源的分配和回收,比如文件(数据、日志、数据库等等)、线程资源、数据库连接等,但它们书写起来却不够优雅。with语句的目的在于从流程图中把try、except、 finally关键字和资源分配、释放相关代码统统去掉,

with处理文件操作的一个实例:

with open('/etc/passwd') as f:for line inf: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语句创建类实例了:

classA: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__ importwith_statementfrom contextlib importcontextmanager

@contextmanagerdefcontext():print 'entering the zone'

try:yield

exceptException, e:print 'with an error %s'%eraiseeelse:print 'with no error'with context():print '----in context call------'

参考文档:

http://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

with语句python_Python之with语句相关推荐

  1. 转:delphi异常捕获try except语句 和 try finally语句用法

    转:http://www.java123.net/v/936977.html      2015-06-24 09:27:48 一直写程序都没管他们,也尽量很少用,今天终于想把他给弄个明白,在网上找来 ...

  2. 【Java】面试官灵魂拷问:if语句执行完else语句真的不会再执行吗?

    写在前面 最近跳槽找工作的朋友确实不少,遇到的面试题也是千奇百怪,这不,一名读者面试时,被面试官问到了一个直击灵魂的问题:if 语句执行完else语句真的不会再执行吗?这个奇葩的问题把这名读者问倒了! ...

  3. R语言嵌套的ifelse语距:将一条If语句放在另一条If语句中,该语句作为嵌套的If else调用。If else语句允许我们根据表达式结果(TRUE或FALSE)打印不同的语句,执行不同的语句块

    R语言嵌套的ifelse语句:将一条If语句放在另一条If语句中,该语句作为嵌套的If else调用.If else语句允许我们根据表达式结果(TRUE或FALSE)打印不同的语句,执行不同的语句块 ...

  4. sqlserver中能用when_sqlserver中if语句顶替when.case.语句

    sqlserver中if语句替代when...case..语句 create table Employees ( EmployeeID char(6) primary key not null, Na ...

  5. mysql等价语句是_Mysql基本语句(个人笔记)

    mysql基本操作语句 1 数据库的基本操作 create database doem default charset utf8; -- 创建数据库 字符编码 utf8 show database; ...

  6. python中用来占位的语句是_python占位语句

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! python pass语句 阅读本文需要0.5分钟 python pass 语句 ...

  7. continue语句只用于循环语句中_循环里continue,break,return的作用,你知道吗?

    循环里continue,break,return的作用,你知道吗?​mp.weixin.qq.com 前言 循环里Continue,Break,Return经常会用到,也是很容易出错的一个坑,今天特地 ...

  8. python可以用break作为变量名_Python初体验(一)—【配置环境变量】【变量】【input】【条件语句】【循环语句】...

    写在前面的: 作为一个控制专业的女研究生,不知道每天在研究什么,但总归逃脱不了码代码的命运.之前也学习过一些C语言.C++,基础嘛,稍稍微有一些.本不想走上码农的道路,天真烂漫的过此生(白日梦过程中. ...

  9. oracle数据定义语句,oracle(sql)基础篇系列(3)——数据维护语句、数据定义语句、伪列...

    oracle(sql)基础篇系列(三)--数据维护语句.数据定义语句.伪列 DML语句 insert 向表中插入新的记录 --三种插入方式 --(1)不写字段的名字,直接按照字段的顺序把值逐个往里插 ...

最新文章

  1. 数据库连接工具datagrip较安全  代替Aqua Data Studio 6.5
  2. cve-2019-1821 思科 Cisco Prime 企业局域网管理器 远程代码执行 漏洞分析
  3. 小程序使用vant-dialog组件内容出不来_微信官方小程序同构新方案Kbone全解析
  4. linux下的awk程序在哪里编写,如何编写awk命令和脚本
  5. 李洋疯狂C语言之求素数的方法
  6. LeetCode 246. 中心对称数(哈希)
  7. 【HP-Unix快捷命令行键详解】
  8. 24.1 新建集成库工程
  9. 试着用java实现DNS(一)——DatagramSocket, DatagramPacket, Message
  10. 系统学习Java语言的15个网站
  11. java版我的世界MITE怎么下_我的世界mite振金版
  12. android 滚动条 惯性,Android ScrollView取消惯性滚动的方法
  13. 增量式编码器与绝对值编码器的区别
  14. Rooting Android
  15. 复旦微的FMQL10S400ZYNQ芯片的多核操作
  16. 关系型数据库--关系代数
  17. 莫比乌斯函数的两种求法(基于欧拉筛、埃氏筛)
  18. 个人日记:XML追加和覆盖内容,将XML某位置的子标签或者属性,文本删除
  19. 有营养的算法笔记(一)
  20. 基于微软专利的带蝴蝶出瞳扩展的光波导结构

热门文章

  1. C#中string.Concat方法的使用
  2. 计算机选修课学什么,计算机专业都学什么 主要课程有什么
  3. armv8 汇编 绝对地址赋值_详解汇编语言B和LDR指令与相对跳转和绝对跳转的关系...
  4. 服务器系统杀毒系统崩溃怎么恢复,系统崩溃是什么原因导致的
  5. redmine两个mysql_Redmine3.4.2安装记(Win10+MySql)
  6. U-BOOT之一:BootLoader 的概念与功能
  7. Linux绘图函数与驱动,Linux中与驱动相关的ioctl函数
  8. linux c++ queue 多线程,C++多线程,消息队列用法
  9. ENVI计算公式(一)
  10. 【转】setsocketopt getsocketopt比较全的参数说明