Python中的with語句與上下文管理器學習總結,

來源:互聯網
上載者:User

Python中的with語句與上下文管理器學習總結,

0、關於上下文管理器
上下文管理器是可以在with語句中使用,擁有__enter__和__exit__方法的對象。

with manager as var:  do_something(var)

相當於以下情況的簡化:

var = manager.__enter__()try:  do_something(var)finally:  manager.__exit__()

換言之,PEP 343中定義的上下文管理器協議允許將無聊的try...except...finally結構抽象到一個單獨的類中,僅僅留下關注的do_something部分。

__enter__方法首先被調用。它可以返回賦給var的值。as部分是可選的:如果它不出現,enter的傳回值簡單地被忽略。
with語句下的代碼被執行。就像try子句,它們或者成功執行到底,或者break,continue或return,或者可以拋出異常。無論哪種情況,該塊結束後,__exit__方法被調用。如果拋出異常,異常資訊被傳遞給__exit__,這將在下一章節討論。通常情況下,異常可被忽略,就像在finally子句中一樣,並且將在__exit__結束後重新拋出。
比如說我們想確認一個檔案在完成寫操作之後被立即關閉:

>>> class closing(object):...  def __init__(self, obj):...   self.obj = obj...  def __enter__(self):...   return self.obj...  def __exit__(self, *args):...   self.obj.close()>>> with closing(open('/tmp/file', 'w')) as f:...  f.write('the contents\n')

這裡我們確保了當with塊退出時調用了f.close()。因為關閉檔案是非常常見的操作,該支援已經出現在file類之中。它有一個__exit__方法調用close,並且本身可作為上下文管理器。

>>> with open('/tmp/file', 'a') as f:...  f.write('more contents\n')

try...finally常見的用法是釋放資源。各種不同的情況實現相似:在__enter__階段資源被獲得,在__exit__階段釋放,如果拋出異常也被傳遞。正如檔案操作,往往這是對象使用後的自然操作,內建支援使之很方便。每一個版本,Python都在更多的地方提供支援。

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()

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.