码迷,mamicode.com
首页 > 编程语言 > 详细

Python之with语句

时间:2015-01-09 17:00:32      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:

Python之with语句

 

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

try:
    ccfile = open(/path/data)
    content = ccfile.readlines()
    ccfile.close()

except IOError:
    log.write(no data read\n)

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

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

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

try:
    try:
        ccfile = open(/path/data)
        content = ccfile.readlines()

    except IOError:
        log.write(no data read\n)

finally
    ccfile.close()

 

finally的另一种可选的风格:

try:
    try:
        ccfile = open(/path/data)
        content = ccfile.readlines()

    finally IOError:
        ccfile.close()

except IOError:
    log.write(no data read\n)

 

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

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

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

class A:  
    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__ import with_statement
from contextlib import contextmanager  

@contextmanager  
def context():
    print entering the zone
    try:
        yield
    except Exception, e:  
        print with an error %s%e
        raise e
    else:
      print with no error  

with context():  
    print ----in context call------ 

 

 

参考文档:

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

 

Python之with语句

标签:

原文地址:http://www.cnblogs.com/chenny7/p/4213447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!