python中的上下文管理器

來源:互聯網
上載者:User

標籤:

參考:http://blog.jobbole.com/64175/

上下文管理器的任務是:代碼塊執行前準備,代碼塊執行後收拾

1、如何使用上下文管理器:

如何開啟一個檔案,並寫入"hello world"

filename="my.txt"mode="w"writer=open(filename,mode)writer.write("hello world")writer.close()

當發生異常時(如磁碟寫滿),就沒有機會執行第5行。當然,我們可以採用try-finally語句塊進行封裝:

writer=open(filename,mode)try:    writer.write("hello world")finally:    writer.close()

當我們進行複雜的操作時,try-finally語句就會變得醜陋,採用with語句重寫:

with open(filename,mode) as writer:    writer.write("hello world")

as指代了從open()函數返回的內容,並把它賦給了新值。with完成了try-finally的任務。

2、自訂上下文管理器

with語句的作用類似於try-finally,提供一種上下文機制。要應用with語句的類,其內部必須提供兩個內建函數__enter__和__exit__。前者在主體代碼執行前執行,後者在主體代碼執行後執行。as後面的變數,是在__enter__函數中返回的。

class echo():    def output(self):        print "hello world"    def __enter__(self):        print "enter"        return self  #可以返回任何希望返回的東西    def __exit__(self,exception_type,value,trackback):        print "exit"        if exception_type==ValueError:            return True        else:            return Flase >>>with echo as e:    e.output()    輸出:enterhello worldexit

完備的__exit__函數如下:

def __exit__(self,exc_type,exc_value,exc_tb)

其中,exc_type:異常類型;exc_value:異常值;exc_tb:異常追蹤資訊

當__exit__返回True時,異常不傳播

3、contextlib模組

contextlib模組的作用是提供更易用的上下文管理器,它是通過Generator實現的。contextlib中的contextmanager作為裝飾器來提供一種針對函數層級的上下文管理機制,常用架構如下:

from contextlib import contextmanager@contextmanagerdef make_context():    print ‘enter‘    try:        yield "ok"    except RuntimeError,err:        print ‘error‘,err    finally:        print ‘exit‘        >>>with make_context() as value:    print value    輸出為:    enter    ok    exit

其中,yield寫入try-finally中是為了保證異常安全(能處理異常)as後的變數的值是由yield返回。yield前面的語句可看作代碼塊執行前操作,yield之後的操作可以看作在__exit__函數中的操作。

以線程鎖為例:

@contextlib.contextmanagerdef loudLock():    print ‘Locking‘    lock.acquire()    yield    print ‘Releasing‘    lock.release() with loudLock():    print ‘Lock is locked: %s‘ % lock.locked()    print ‘Doing something that needs locking‘ #Output:#Locking#Lock is locked: True#Doing something that needs locking#Releasing

4、contextlib.nested:減少嵌套

對於:

with open(filename,mode) as reader:    with open(filename1,mode1) as writer:        writer.write(reader.read())

可以通過contextlib.nested進行簡化:

with contextlib.nested(open(filename,mode),open(filename1,mode1)) as (reader,writer):    writer.write(reader.read())

在python 2.7及以後,被一種新的文法取代:

with open(filename,mode) as reader,open(filename1,mode1) as writer:    writer.write(reader.read())

5、contextlib.closing()

file類直接支援上下文管理器API,但有些表示開啟控制代碼的對象並不支援,如urllib.urlopen()返回的對象。還有些遺留類,使用close()方法而不支援上下文管理器API。為了確保關閉控制代碼,需要使用closing()為它建立一個上下文管理器(調用類的close方法)。

import contextlibclass myclass():    def __init__(self):        print ‘__init__‘    def close(self):        print ‘close()‘     with contextlib.closing(myclass()):    print ‘ok‘    輸出:__init__okclose()


python中的上下文管理器

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.