前言

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,

比如文件使用后自动关闭/线程中锁的自动获取和释放等。

问题引出

如下代码:

file = open("1.txt")
data = file.read()
file.close()

上面代码存在2个问题: 
(1)文件读取发生异常,但没有进行任何处理; 
(2)可能忘记关闭文件句柄;

改进

try:
f = open('xxx')
except:
print('fail to open')
exit(-1)
try:
do something
except:
do something
finally:
f.close()

虽然这段代码运行良好,但比较冗长。 
而使用with的话,能够减少冗长,还能自动处理上下文环境产生的异常。如下面代码:

with open("1.txt") as file:
data = file.read()

with 工作原理

(1)紧跟with后面的语句被求值后,返回对象的“–enter–()”方法被调用,这个方法的返回值将被赋值给as后面的变量; 
(2)当with后面的代码块全部被执行完之后,将调用前面返回对象的“–exit–()”方法。 
with工作原理代码示例:

class Sample:
def __enter__(self):
print "in __enter__"
return "Foo"
def __exit__(self, exc_type, exc_val, exc_tb):
print "in __exit__"
def get_sample():
return Sample()
with get_sample() as sample:
print "Sample: ", sample

代码的运行结果如下:

in __enter__
Sample: Foo
in __exit__

可以看到,整个运行过程如下: 
(1)enter()方法被执行; 
(2)enter()方法的返回值,在这个例子中是”Foo”,赋值给变量sample; 
(3)执行代码块,打印sample变量的值为”Foo”; 
(4)exit()方法被调用;

【注:】exit()方法中有3个参数, exc_type, exc_val, exc_tb,这些参数在异常处理中相当有用。 
exc_type: 错误的类型 
exc_val: 错误类型对应的值 
exc_tb: 代码中错误发生的位置 
示例代码:

class Sample():
def __enter__(self):
print('in enter')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print "type: ", exc_type
print "val: ", exc_val
print "tb: ", exc_tb
def do_something(self):
bar = 1 / 0
return bar + 10
with Sample() as sample:
sample.do_something()

程序输出结果:

in enter
Traceback (most recent call last):
type: <type 'exceptions.ZeroDivisionError'>
val: integer division or modulo by zero
File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 36, in <module>
tb: <traceback object at 0x7f9e13fc6050>
sample.do_something()
File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 32, in do_something
bar = 1 / 0
ZeroDivisionError: integer division or modulo by zero Process finished with exit code 1

总结

实际上,在with后面的代码块抛出异常时,exit()方法被执行。开发库时,清理资源,关闭文件等操作,都可以放在exit()方法中。 
总之,with-as表达式极大的简化了每次写finally的工作,这对代码的优雅性是有极大帮助的。 
如果有多项,可以这样写:

With open('1.txt') as f1, open('2.txt') as  f2:
do something

参考网址

http://blog.kissdata.com/2014/05/23/python-with.html

python 中 with 用法的更多相关文章

  1. python中xrange用法分析

    本文实例讲述了python中xrange用法.分享给大家供大家参考.具体如下: 先来看如下示例: >>> x=xrange(0,8) >>> print x xra ...

  2. python 中@ 的用法【转】

    这只是我的个人理解: 在Python的函数中偶尔会看到函数定义的上一行有@functionName的修饰,当解释器读到@的这样的修饰符之后,会先解析@后的内容,直接就把@下一行的函数或者类作为@后边的 ...

  3. Python中flatten用法

    Python中flatten用法 原创 2014年04月16日 10:20:02 标签: Python / flatten 22667 一.用在数组 >>> a = [[1,3],[ ...

  4. 列表[‘hello’ , ‘python’ ,’!’ ] 用多种方法拼接,并输出’hello python !’ 以及join()在python中的用法简介

    列表[‘hello’ , ‘python’ ,’!’ ] 用多种方法拼接,并输出’hello python !’ 使用字符串链接的四种方法都可以创建 字符串拼接一共有四种方法,也可以应用到列表的拼接中 ...

  5. python中“end=”用法

    python中“end=”用法:例如print(“#”,end=" \n"),默认换行,print(“#”,end=" ")则在循环中不换行

  6. python中pkl用法

    原文连接:https://www.jianshu.com/p/2ecadebe6d13 python中pkl用法 经常遇到在Python程序运行得到了一些字符串.列表.字典等数据,想要长久的保存下来, ...

  7. Python中print用法里面% ,"%s 和 % d" 代表的意思

    Python 编程 里面% . "%s 和 % d" 代表的意思 %s,表示格化式一个对象为字符 %d,整数 "Hello, %s"%"zhang3& ...

  8. 详解python中@的用法

    python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...

  9. python中*的用法

    在python中,很多情况下会用到*,下面举一些例子来说明*的用法 1.数字计算中,*代表乘法,**代表求幂 print('2乘以3值为:%s'%(2*3)) print('2的3次方值为:%s'%( ...

  10. python中print用法

    print用法 参考文档:https://blog.csdn.net/sinat_28576553/article/details/81154912 目录 一.print()函数概述 二.变量的输出 ...

随机推荐

  1. 【系统】supervisor支持多进程

    [program:deployworker] directory = /etc/ansible/easyAnsible/app/deploy/ command = python Deploy.py p ...

  2. Medication Reconciliation Overview

    http://www.hcsinc.net/HCS-Medication-Reconciliation/med-rec-overview.html At HCS, we've worked with ...

  3. android 动画具体解释(二)

    以下就開始学习属性动画的基本使用方法,我们来看属性动画的继承关系,例如以下如所看到的: 显然关注的焦点应该是ValueAnimator,ObjectAnimator这两个类啦,ObjectAnimat ...

  4. Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他

    现在开发中的功能需要直接跳转到拨号.联系人.短信界面等等,查找了很多资料,自己整理了一下. 首先,我们先看拨号界面,代码如下: Intent intent =new Intent(); intent. ...

  5. Oracle 之 获取当前日期及日期格式化

    Oracle 获取当前日期及日期格式: 获取系统日期:  SYSDATE 格式化日期: TO_CHAR(SYSDATE, 'YY/MM/DD HH24:MI:SS)                   ...

  6. Ubuntu下的多线程下载工具:MultiGet;并与 Firefox 建立关联 uget

    Ubuntu下非常给力的下载工具--uget+aria2 1.uget的安装: sudo add-apt-repository ppa:plushuang-tw/uget-stable sudo ap ...

  7. html5开放资料

    http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html KineticJS教程(12) 摘要: KineticJS教程(12) 作者 ...

  8. taro 在components文件夹中 新建组件时,组件支持自定义命名,但是不能大写开头

    在components文件夹中 新建组件时,组件支持自定义命名,但是不能大写开头.否则会报错 错误写法: // 真实路径 import MinaMask from '../../components/ ...

  9. html-webpack-plugin插件 根据模板生成多页面

    1.项目目录结构为: 2.webpack.config.js配置文件为: var htmlWebpackPlugin = require('html-webpack-plugin'); module. ...

  10. 马老师 Linux基础入门

    总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束, 按照计算机所传输的信息种类,计算机的总线可以划分为数据总线.地址总线和控制总线,分别用来传输数据.数据地址和控 ...