A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. When an exception has occurred in thetry clause and has not been handled by anexcept clause (or it has occurred in aexcept orelse clause), it is re-raised after thefinally clause has been executed. Thefinally clause is also executed “on the way out” when any other clause of thetry statement is left via abreak,continue orreturn statement. A more complicated example (havingexcept andfinally clauses in the sametry statement works as of Python 2.5):
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print "division by zero!"
... else:
... print "result is", result
... finally:
... print "executing finally clause"
...
>>> divide(2, 1)
result is 2
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
As you can see, the finally clause is executed in any event. TheTypeError raised by dividing two strings is not handled by theexcept clause and therefore re-raised after thefinally clause has been executed.
In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.
8.7. Predefined Clean-up Actions
Some objects define standard clean-up actions to be undertaken when the object is no longer needed, regardless of whether or not the operation using the object succeeded or failed. Look at the following example, which tries to open a file and print its contents to the screen.
for line in open("myfile.txt"):
print line
The problem with this code is that it leaves the file open for an indeterminate amount of time after the code has finished executing. This is not an issue in simple scripts, but can be a problem for larger applications. Thewith statement allows objects like files to be used in a way that ensures they are always cleaned up promptly and correctly.
with open("myfile.txt") as f:
for line in f:
print line
After the statement is executed, the file f is always closed, even if a problem was encountered while processing the lines. Other objects which provide predefined clean-up actions will indicate this in their documentation.
=====================================with的用法===============================================
01.>>> class A:
02. def __enter__(self):
03. print 'in enter'
04. def __exit__(self, e_t, e_v, t_b):
05. print 'in exit'
06.
07.>>> with A() as a:
08. print 'in with'
09.
10.in enter
11.in with
12.in exit
with从Python 2.5就有,需要from __future__ import with_statement。自python 2.6开始,成为默认关键字。
也就是说with是一个控制流语句,跟if/for/while/try之类的是一类的,with可以用来简化try finally代码,看起来可以比try finally更清晰。
这里新引入了一个"上下文管理协议"context management protocol,实现方法是为一个类定义__enter__和__exit__两个函数。
with expresion as variable的执行过程是,首先执行__enter__函数,它的返回值会赋给as后面的variable,想让它返回什么就返回什么,只要你知道怎么处理就可以了,如果不写as variable,返回值会被忽略。
然后,开始执行with-block中的语句,不论成功失败(比如发生异常、错误,设置sys.exit()),在with-block执行完成后,会执行__exit__函数。
这样的过程其实等价于:
只不过,现在把一部分代码封装成了__enter__函数,清理代码封装成__exit__函数。
我们可以自己实现一个例子:
注意:
1、t不是test()的值,test()返回的是"context manager object",是给with用的。t获得的是__enter__函数的返回值,这是with拿到test()的对象执行之后的结果。t的值是1.
2、__exit__函数的返回值用来指示with-block部分发生的异常是否要re-raise,如果返回False,则会re-raise with-block的异常,如果返回True,则就像什么都没发生。
一 with
python中的with的作用是自动释放对象,即使对象在使用的过程中有异常抛出。可以使用with的类型必须实现__enter__ __exit__。我的理解是=try...finally{},在finally中调用了释放函数。
[类似与CSharp中的using(){}关键字,用来自动确保调用对象的dispose()方法,即使对象有异常抛出。C#中可以使用using{}的对象必须已经实现了IDispose接口。]
with open( " myfile.txt " ) as f:
for line in f:
print (line)
f.readline() # f is already clean up here, here will meet ValueError exception
TestWith()
在with语句执行完以后,f对象马上就被释放了。所以下面在调用f.readline()会出错。
二 with + try...except
既能让对象自动释放,又包含了异常捕获的功能。
def __init__ (self, filename):
self.filename = filename
self.f = None
def __enter__ (self):
try :
f = open(self.filename, ' r ' )
content = f.read()
return content
except IOError as e:
print (e)
def __exit__ (self, type, value, traceback):
if self.f:
print ( ' type:%s, value:%s, traceback:%s ' % (str(type), str(value), str(traceback)))
self.f.close()
def TestWithAndException():
with controlled_execution( " myfile.txt " ) as thing:
if thing:
print (thing)
# TestWithAndException()