標籤:log 對象 lock enter font already 返回 ace err
1、with操作符
在python中讀寫檔案,可能需要這樣的代碼
try-finally讀寫檔案
file_text = Nonetry: file_text = open(‘./text‘, ‘r‘) print file_text.read()except IOError, ex: traceback.print_exc()finally: if file_text: file_text.close()
同樣,在python中使用線程鎖,可能需要這樣的代碼
try-finally線程鎖
lock = threading.Lock()lock.acquire()try: passexcept Exception, ex: traceback.print_exc()finally: lock.release()
可能你會覺得這種寫法很不方便,python提供了with操作符,你可以這樣操作
with讀寫檔案
with open(‘./text‘, ‘r‘) as file_text: print file_text.read()
with線程鎖
with lock: pass
是不是方便多了。
其實,不只是lock和file可以使用with操作符。
實際上,任何對象,只要正確實現上下文管理,就可以使用with語句。實現上下文管理是通過 __enter__ 和 __exit__ 這兩個方法實現的。
2、上下文管理
上下文管理可以為我們屏蔽內容相關的複雜性。例如,我們實現一個類Cat,實現其__enter__和__exit__方法。
__enter__(self): 進入上下文管理器時調用此方法,其傳回值將被放入with-as語句中as說明符指定的變數中。
__exit__(self,type,value,tb):離開上下文管理器調用此方法。如果有異常出現,type、value、tb分別為異常的類型、值和追蹤資訊。如果沒有異常,
3個參數均設為None。此方法傳回值為True或者False,分別指示被引發的異常得到了還是沒有得到處理。如果返回False,引發的異常會被傳遞出上下文。
如下。
class Cat(object): def __init__(self, name): self.name = name def __enter__(self): print ‘enter from Cat named %s‘ % self.name return self def hello(self): print ‘hello, %s‘ % self.name def __exit__(self, exc_type, exc_val, exc_tb): print ‘exit from Cat named %s‘ % self.name
執行,並列印結果
with Cat(‘Tom‘) as tom: tom.hello()enter from Cat named Tomhello, Tomexit from Cat named Tom
這裡我們執行as tom獲得了Cat類的一個執行個體,這是通過__enter__方法的返回得到的。
當然,我們可以管理多個,請注意進入和退出的順序。
with Cat(‘Tom‘) as tom, Cat(‘Harry‘) as harry: tom.hello() harry.hello()enter from Cat named Tomenter from Cat named Harryhello, Tomhello, Harryexit from Cat named Harryexit from Cat named Tom
3、contextmanager
可能你還是覺得實現__enter__和__exit__很麻煩。python提供了contextlib.contextmanager
讓我們重寫上面的例子,使用contextmanager
from contextlib import contextmanager as _contextmanager@_contextmanagerdef cat(name): print ‘enter cat named %s‘ % name yield name print ‘exit cat named %s‘ % name
執行,並列印結果
with cat(‘Kitty‘) as kitty: print ‘hello, %s‘ % kittyenter cat named Kittyhello, Kittyexit cat named Kitty
as後面的執行個體,是通過yield語句返回的。這裡是返回了一個字串。
當然,同樣支援管理多個執行個體
with cat(‘Kitty‘) as kitty, cat(‘Tom‘) as tom: print ‘hello, %s‘ % kitty print ‘hello, %s‘ % tomenter cat named Kittyenter cat named Tomhello, Kittyhello, Tomexit cat named Tomexit cat named Kitty
4、最後給出一個執行個體
使用上線文管理器實現redis分布式鎖
import redisimport timeimport threadingimport tracebackfrom contextlib import contextmanager as _contextmanagerr = redis.Redis(host=‘localhost‘, port=6379, db=0)@_contextmanagerdef dist_lock(client, key): dist_lock_key = ‘lock:%s‘ % key try: _acquire_lock(client, dist_lock_key) yield _release_lock(client, dist_lock_key) except Exception, ex: passdef _acquire_lock(client, key): is_lock = r.set(key, 1, nx=True, ex=10) if not is_lock: raise Exception("already locked!")def _release_lock(client, key): client.delete(key)def func(): while 1: try: with dist_lock(r, "key"): print "*" time.sleep(8) except Exception, ex: passthread_list = list()for i in range(10): thread_list.append(threading.Thread(target=func))for thread in thread_list: thread.start()for thread in thread_list: thread.join()
python contextlib 上下文管理器