转自http://sdqali.in/blog/2012/07/09/understanding-pythons-with/
Understanding Python's "with" statement
09 July 2012
What is it?
Python’s with
statement provides a very convenient way of dealing with the situation where you have to do a setup and teardown to make something happen. A very good example for this is the situation where you want to gain a handler to a file, read data from the file and the close the file handler.
Without the with
statement, one would write something along the lines of:
file = open("/tmp/foo.txt") data = file.read() file.close()
There are two annoying things here. First, you end up forgetting to close the file handler. The second is how to handle exceptions that may occur once the file handler has been obtained. One could write something like this to get around this:
file = open("/tmp/foo.txt") try: data = file.read() finally: file.close()
While this works well, it is unnecessarily verbose. This is where with
is useful. The good thing about with
apart from the better syntax is that it is very good handling exceptions. The above code would look like this, when using with
:
with open("/tmp/foo.txt") as file: data = file.read()
How does it work?
While this might look like magic, the way Python handles with
is more clever than magic. The basic idea is that the statement after with
has to evaluate an object that responds to an __enter__()
as well as an __exit__()
function.
After the statement that follows with
is evaluated, the __enter__()
function on the resulting object is called. The value returned by this function is assigned to the variable following as
. After every statement in the block is evaluated, the __exit__()
function is called.
This can be demonstrated with the following example:
#!/usr/bin/env python # with_example01.py class Sample: def __enter__(self): print "In __enter__()" return "Foo" def __exit__(self, type, value, trace): print "In __exit__()" def get_sample(): return Sample() with get_sample() as sample: print "sample:", sample
When executed, this will result in:
bash-3.2$ ./with_example01.py In __enter__() sample: Foo In __exit__()
As you can see,
- The
__enter__()
function is executed - The value returned by it – in this case
"Foo"
is assigned tosample
- The body of the block is executed, thereby printing the value of
sample
ie."Foo"
- The
__exit__()
function is called.
What makes with
really powerful is the fact that it can handle exceptions. You would have noticed that the __exit__()
function for Sample
takes three arguments – val
, type
and trace
. These are useful in exception handling. Let’s see how this works by modifying the above example.
#!/usr/bin/env python # with_example02.py class Sample: def __enter__(self): return self def __exit__(self, type, value, trace): print "type:", type print "value:", value print "trace:", trace def do_something(self): bar = 1/0 return bar + 10 with Sample() as sample: sample.do_something()
Notice how in this example, instead of get_sample()
, with
takes Sample()
. It does not matter, as long as the statement that follows with
evaluates to an object that has an __enter__()
and __exit__()
functions. In this case, Sample()
’s __enter__()
returns the newly created instance of Sample
and that is what gets passed to sample
.
When executed:
bash-3.2$ ./with_example02.py type: <type 'exceptions.ZeroDivisionError'> value: integer division or modulo by zero trace: <traceback object at 0x1004a8128> Traceback (most recent call last): File "./with_example02.py", line 19, in <module> sample.do_something() File "./with_example02.py", line 15, in do_something bar = 1/0 ZeroDivisionError: integer division or modulo by zero
Essentially, if there are exceptions being thrown from anywhere inside the block, the __exit__()
function for the object is called. As you can see, the type, value and the stack trace associated with the exception thrown is passed to this function. In this case, you can see that there was a ZeroDivisionError
exception being thrown. People implementing libraries can write code that clean up resources, close files etc. in their __exit__()
functions.
Thus, Python’s with
is a nifty construct that makes code a little less verbose and makes cleaning up during exceptions a bit easier.
I have put the code examples given here on Github.
相关推荐
VB With语句块实例 VB With语句块实例
关于python的with语句使用,学习Python有一段时间了,最近做一个项目会涉及到文件的读取和关闭。比如:我想把一些对象序列化到文件里面,然后当我再次使用的时候,在从文件 里面读取反序列化成对象。像这种操作一般都...
python中的with语句使用于对资源进行访问的场合,保证不管处理过程中是否发生错误或者异常都会执行规定的__exit__(“清理”)操作,释放被访问的资源,比如有文件读写后自动关闭、线程中锁的自动获取和释放等。...
152-4 使用With语句引用对象.xlsm
DB2公共表表达式(WITH语句使用).pdf
主要介绍了Javascript中With语句用法,实例分析了javascript中with语句的相关使用方法,类似VB语句的用法,需要的朋友可以参考下
本文实例讲述了python with语句的原理与用法。分享给大家供大家参考,具体如下: 之前看到一篇博客说博主python面试时遇到面试官提问with的原理,而那位博主的博文没有提及with原理,故有此文。 关于with语句,官方...
javascript完美学习视频教程-----11.javascript流程控制-跳转语句、with语句
JavaScript 有个 with 关键字, with 语句的原本用意是为逐级的对象访问提供命名空间式的速写方式。这篇文章主要介绍了JavaScript中with语句的相关知识,感兴趣的朋友一起学习吧
我们可以通过with语句结合上下文管理器简化一些操作。 使用with语句结合自定义上下文管理器完成数据库相应的操作,代码实现如下: # 1. 导入模块 import pymysql # 创建自定义上下文管理器对象 class MyDatabase...
python学习笔记,包含迭代器-生成器-with语句和上下文管理器-修饰符
主要介绍了Python中的With语句的使用及原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
主要介绍了Vue js with语句原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
一、简介 with是从Python 2.5 引入的一个新的语法,更准确的说,是一种上下文的管理协议,用于...复制代码 代码如下:with EXPR as VAR: BLOCK根据PEP 343的解释,with…as…会被翻译成以下语句:复制代码 代码如下:mg
本篇文章主要介绍了Python中的上下文管理器和with语句的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
在Python中作为上下文管理器的对象可以使用with语句,提供上下文管理器的contextlib模块的使用则是Python编程中的高级技巧,下面我们就来详细整理一下Python中的with语句与上下文管理器学习总结:
with语句和上下文管理器`启程“下面进行with语句的剖析,在自定义对象中支持with“进阶“加深理解“探索` 启程 with 语句究竟有哪些好处?它有助于简化一些通用资源管理模式,抽象出其中的功能,将其分解并重用...
with 语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from __future__ import with_statement 导入后才可以使用),从 2.6 版本开始缺省可用(参考 What’s new in Python 2.6? 中 with...