python中關於with及contextlib的用法


    平常Coding過程中,經常使用到的with場景是(打開文件進行文件處理,然后隱式地執行了文件句柄的關閉,同樣適合socket之類的,這些類都提供了對with的支持):

with file('test.py','r') as f :
    print f.readline()

    with的作用,類似try...finally...,提供一種上下文機制,要應用with語句的類,其內部必須提供兩個內置函數__enter__以及__exit__。前者在主體代碼執行前執行,后則在主體代碼執行后執行。as后面的變量,是在__enter__函數中返回的。通過下面這個代碼片段以及注釋說明,可以清晰明白__enter__與__exit__的用法:

#!encoding:utf-8
class echo :
    def output(self) :
        print 'hello world'
    def __enter__(self):
        print 'enter'
        return self #返回自身實例,當然也可以返回任何希望返回的東西
    def __exit__(self, exception_type, exception_value, exception_traceback):
        #若發生異常,會在這里捕捉到,可以進行異常處理
        print 'exit'
        #如果改__exit__可以處理改異常則通過返回True告知該異常不必傳播,否則返回False
        if exception_type == ValueError :
            return True
        else:
            return False
 
with echo() as e:
    e.output()
    print 'do something inside'
print '-----------'
with echo() as e:
    raise ValueError('value error')
print '-----------'
with echo() as e:
    raise Exception('can not detect')

運行結果:

QQ截圖20130128171206

 

contextlib是為了加強with語句,提供上下文機制的模塊,它是通過Generator實現的。通過定義類以及寫__enter__和__exit__來進行上下文管理雖然不難,但是很繁瑣。contextlib中的contextmanager作為裝飾器來提供一種針對函數級別的上下文管理機制。常用框架如下:

from contextlib import contextmanager
 
@contextmanager
def make_context() :
    print 'enter'
    try :
        yield {}
    except RuntimeError, err :
        print 'error' , err
    finally :
        print 'exit'
 
with make_context() as value :
    print value

contextlib還有連個重要的東西,一個是nested,一個是closing,前者用於創建嵌套的上下文,后則用於幫你執行定義好的close函數。但是nested已經過時了,因為with已經可以通過多個上下文的直接嵌套了。下面是一個例子:

from contextlib import contextmanager
from contextlib import nested
from contextlib import closing
@contextmanager
def make_context(name) :
    print 'enter', name
    yield name
    print 'exit', name
 
with nested(make_context('A'), make_context('B')) as (a, b) :
    print a
    print b
 
with make_context('A') as a, make_context('B') as b :
    print a
    print b
 
class Door(object) :
    def open(self) :
        print 'Door is opened'
    def close(self) :
        print 'Door is closed'
 
with closing(Door()) as door :
    door.open()

運行結果:

總結:python有很多強大的特性,由於我們平常總習慣於之前C++或java的一些編程習慣,時常忽略這些好的機制。因此,要學會使用這些python特性,讓我們寫的python程序更像是python。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM