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

With语句是什么?

有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

如果不用with语句,代码如下:

  1. file = open("/tmp/foo.txt")
  2. data = file.read()
  3. file.close()

这里有两个问题:

  1. 一是可能忘记关闭文件句柄;
  2. 二是文件读取数据发生异常,没有进行任何处理。

下面是处理异常的加强版本:

  1. try:
  2. f = open('xxx')
  3. except:
  4. print 'fail to open'
  5. exit(-1)
  6. try:
  7. do something
  8. except:
  9. do something
  10. finally:
  11. f.close()

虽然这段代码运行良好,但是太冗长了。

这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。

下面是with版本的代码:

  1. with open("/tmp/foo.txt") as file:
  2. data = file.read()

with如何工作?

  • 紧跟with后面的语句被求值后,返回对象的 __enter__() 方法被调用,这个方法的返回值将被赋值给as后面的变量。
  • 当with后面的代码块全部被执行完之后,将调用前面返回对象的 __exit__()方法。

下面例子可以具体说明with如何工作:

  1. #!/usr/bin/env python
  2. # with_example01.py
  3. class Sample:
  4. def __enter__(self):
  5. print "In __enter__()"
  6. return "Foo"
  7. def __exit__(self, type, value, trace):
  8. print "In __exit__()"
  9. def get_sample():
  10. return Sample()
  11. with get_sample() as sample:
  12. print "sample:", sample

运行代码,输出如下

  1. bash-3.2$ ./with_example01.py
  2. In __enter__()
  3. sample: Foo
  4. In __exit__()

正如你看到的: 1. __enter__()方法被执行 2. __enter__()方法返回的值 - 这个例子中是”Foo”,赋值给变量’sample’ 3. 执行代码块,打印变量”sample”的值为 “Foo” 4. __exit__()方法被调用 with真正强大之处是它可以处理异常。

可能你已经注意到Sample类的 __exit__ 方法有三个参数 val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。

  1. #!/usr/bin/env python
  2. # with_example02.py
  3. class Sample:
  4. def __enter__(self):
  5. return self
  6. def __exit__(self, type, value, trace):
  7. print "type:", type
  8. print "value:", value
  9. print "trace:", trace
  10. def do_something(self):
  11. bar = 1/0
  12. return bar + 10
  13. with Sample() as sample:
  14. sample.do_something()

这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有 __enter__() 和 __exit__() 方法即可。此例中,Sample()的 __enter__() 方法返回新创建的Sample对象,并赋值给变量sample。

代码执行后:

  1. bash-3.2$ ./with_example02.py
  2. type: <type 'exceptions.ZeroDivisionError'>
  3. value: integer division or modulo by zero
  4. trace: <traceback object at 0x1004a8128>
  5. Traceback (most recent call last):
  6. File "./with_example02.py", line 19, in <module>
  7. sample.do_something()
  8. File "./with_example02.py", line 15, in do_something
  9. bar = 1/0
  10. ZeroDivisionError: integer division or modulo by zero

实际上,在with后面的代码块抛出任何异常时,__exit__() 方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给 __exit__() 方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在 __exit__ 方法当中。

另外,__exit__ 除了用于tear things down,还可以进行异常的监控和处理,注意后几个参数。要跳过一个异常,只需要返回该函数True即可。

下面的样例代码跳过了所有的TypeError,而让其他异常正常抛出。

  1. def __exit__(self, type, value, traceback):
  2. return isinstance(value, TypeError)

上文说了 __exit__ 函数可以进行部分异常的处理,如果我们不在这个函数中处理异常,他会正常抛出,这时候我们可以这样写(python 2.7及以上版本,之前的版本参考使用contextlib.nested这个库函数):

  1. try:
  2. with open( "a.txt" ) as f :
  3. do something
  4. except xxxError:
  5. do something about exception

总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码的优雅性是有极大帮助的。

如果有多个项,我们可以这么写:

  1. with open("x.txt") as f1, open('xxx.txt') as f2:
  2. do something with f1,f2

因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。

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

  1. Python回调函数用法实例详解

    本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函 ...

  2. day01-day04总结- Python 数据类型及其用法

    Python 数据类型及其用法: 本文总结一下Python中用到的各种数据类型,以及如何使用可以使得我们的代码变得简洁. 基本结构 我们首先要看的是几乎任何语言都具有的数据类型,包括字符串.整型.浮点 ...

  3. 【Python】关于Python有意思的用法

    开一篇文章,记录关于Python有意思的用法,不断更新 1.Python树的遍历 def sum(t): tmp=0 for k in t: if not isinstance(k,list): tm ...

  4. python中xrange用法分析

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

  5. 浅谈Python在信息学竞赛中的运用及Python的基本用法

    浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...

  6. python scapy的用法之ARP主机扫描和ARP欺骗

    python scapy的用法之ARP主机扫描和ARP欺骗 目录: 1.scapy介绍 2.安装scapy 3.scapy常用 4.ARP主机扫描 5.ARP欺骗 一.scapy介绍 scapy是一个 ...

  7. python函数的用法

    python函数的用法 目录: 1.定义.使用函数 1.函数定义:def 2.函数调用:例:myprint() 3.函数可以当作一个值赋值给一个变量 例:a=myprint()    a() 4.写r ...

  8. python 中@ 的用法【转】

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

  9. Python Enum 枚举 用法汇总

    Python Enum 枚举 用法汇总 import os import sys if sys.version_info.major + sys.version_info.minor * 0.1 &l ...

  10. python查看对象用法

    python查看类用法: dir(object_name)

随机推荐

  1. MAC OSX Docker安装教程2018

    1.首先打开Docker商店 Docker商店地址:https://store.docker.com/editions/community/docker-ce-desktop-mac 2.打开后界面如 ...

  2. python 输出环境变量

    import os # Access all environment variables print('*---------------ENVIRON-------------------*') pr ...

  3. Tensorflow一些常用基本概念与函数(三)

    摘要:本系列主要对tf的一些常用概念与方法进行描述.本文主要针对tensorflow的数据IO.图的运行等相关函数进行讲解.为‘Tensorflow一些常用基本概念与函数’系列之三. 1.序言 本文所 ...

  4. POJ 3087 Shuffle'm Up 线性同余,暴力 难度:2

    http://poj.org/problem?id=3087 设:s1={A1,A2,A3,...Ac} s2={Ac+1,Ac+2,Ac+3,....A2c} 则 合在一起成为 Ac+1,A1,Ac ...

  5. hdu 6154 CaoHaha's staff

    CaoHaha's staff Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  6. Backbone设计思路和关键源码分析

    一. Backbone的江湖地位: backbone作为一个老牌js框架为大规模前端开发提供了新的开发思路:前端MVC模式,这个模式也是前端开发演变过程中的一个重要里程碑,也为MVVM和Redux等开 ...

  7. Win7操作系统安装IE10提示“安装前需要更新与安装程序版本”

    安装IE10浏览器时提示错误的 Internet Explorer安装程序版本 故障现象: Win7操作系统在安装IE10浏览器时会弹出对话框,提示错误的Ieternet Explorer 安装程序版 ...

  8. 64位的ubuntu14.04 LTS安装 Linux交叉编译工具链及32位“ia32-libs”依赖库

    ubuntu又迎来了其新一代的长期支持版本 14.04 LTS,其带来了许多令人期待的新特新,遂决定进行升级. 装好了64位版本及安装 Linux交叉编译工具链 运行GCC,${CROSS_COMPI ...

  9. 各开源 bbs 程序比较

    主要是集中在 php 开源轻巧的程序. 搜索到一个逼乎的一个帖子:https://www.zhihu.com/question/20655704 ,顺藤摸瓜 下. carbon forum 第一个测试 ...

  10. [leetcode] 204. Count Primes 统计小于非负整数n的素数的个数

    题目大意 https://leetcode.com/problems/count-primes/description/ 204. Count Primes Count the number of p ...