国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

詳解Python中contextlib上下文管理模塊的用法

2019-11-25 16:41:20
字體:
來源:轉載
供稿:網友

咱們用的os模塊,讀取文件的時候,其實他是含有__enter__ __exit__ 。  一個是with觸發的時候,一個是退出的時候。

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

那咱們自己再實現一個標準的可以with的類。 我個人寫python的時候,喜歡針對一些需要有關閉邏輯的代碼,構造成with的模式 。 

#encoding:utf-8class echo:  def __enter__(self):    print 'enter'   def __exit__(self,*args):    print 'exit' with echo() as e:  print 'nima'

contextlib是個比with優美的東西,也是提供上下文機制的模塊,它是通過Generator裝飾器實現的,不再是采用__enter__和__exit__。contextlib中的contextmanager作為裝飾器來提供一種針對函數級別的上下文管理機制。

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

我這里再貼下我上次寫的redis分布式鎖代碼中有關于contextlib的用法。其實乍一看,用了with和contextlib麻煩了,但是最少讓你的主體代碼更加鮮明了。

from contextlib import contextmanagerfrom random import random DEFAULT_EXPIRES = 15DEFAULT_RETRIES = 5 @contextmanagerdef dist_lock(key, client):  key = 'lock_%s' % key   try:    _acquire_lock(key, client)    yield  finally:    _release_lock(key, client) def _acquire_lock(key, client):  for i in xrange(0, DEFAULT_RETRIES):    get_stored = client.get(key)    if get_stored:      sleep_time = (((i+1)*random()) + 2**i) / 2.5      print 'Sleeipng for %s' % (sleep_time)      time.sleep(sleep_time)    else:      stored = client.set(key, 1)      client.expire(key,DEFAULT_EXPIRES)      return  raise Exception('Could not acquire lock for %s' % key) def _release_lock(key, client):  client.delete(key)


Context Manager API

一個上下文管理器通過with聲明激活, 而且API包含兩個方法。__enter__()方法運行執行流進入到with代碼塊內。他返回一個對象共上下文使用。當執行流離開with塊時,__exit__()方法上下文管理器清除任何資源被使用。

class Context(object):    def __init__(self):    print '__init__()'  def __enter__(self):    print '__enter__()'    return self  def __exit__(self, exc_type, exc_val, exc_tb):    print '__exit__()'with Context():  print 'Doing work in the context.'

打印結果

__init__()__enter__()Doing work in the context.__exit__()

執行上下文管理器時會調用__enter__離開時調用__exit__。

__enter__能返回任意對象,聯合一個指定名字于with聲明。

class WithinContext(object):  def __init__(self, context):    print 'WithinContext.__init__(%s)' % context  def do_something(self):    print 'WithinContext.do_something()'  def __del__(self):    print 'WithinContext.__del__'class Context(object):  def __init__(self):    print '__init__()'    def __enter__(self):    print '__enter__()'    return WithinContext(self)    def __exit__(self, exc_type, exc_val, exc_tb):    print '__exit__()'with Context() as c:  c.do_something()

打印結果

__init__()__enter__()WithinContext.__init__(<__main__.Context object at 0x7f579d8e4890>)WithinContext.do_something()__exit__()WithinContext.__del__

如果上下文管理器能處理異常,__exit__()應該返回一個True值表明這個異常不需要傳播,返回False異常會在執行__exit__之后被引起。

class Context(object):  def __init__(self, handle_error):    print '__init__(%s)' % handle_error    self.handle_error = handle_error    def __enter__(self):    print '__enter__()'    return self    def __exit__(self, exc_type, exc_val, exc_tb):    print '__exit__(%s, %s, %s)' % (exc_type, exc_val, exc_tb)    return self.handle_errorwith Context(True):  raise RuntimeError('error message handled')printwith Context(False):  raise RuntimeError('error message propagated')

打印結果

__init__(True)__enter__()__exit__(<type 'exceptions.RuntimeError'>, error message handled, <traceback object at 0x7fdfb32f8b00>)__init__(False)__enter__()__exit__(<type 'exceptions.RuntimeError'>, error message propagated, <traceback object at 0x7fdfb32f8b90>)Traceback (most recent call last): File "test.py", line 23, in <module>   raise RuntimeError('error message propagated')   RuntimeError: error message propagated


從生成器到上下文管理器

創建上下文管理的傳統方法,通過編寫一個類與__enter__()和__exit__()方法,并不困難。但有時比你需要的開銷只是管理一個微不足道的上下文。在這類情況下,您可以使用contextmanager() decorat or 生成器函數轉換成一個上下文管理器。

import contextlib@contextlib.contextmanagerdef make_context():  print ' entering'  try:    yield {}   except RuntimeError, err:    print ' Error:', err  finally:    print ' exiting'    print 'Normal:'with make_context() as value:  print ' inside with statement:', value  printprint 'handled ereor:'with make_context() as value:  raise RuntimeError('show example of handling an error')printprint 'unhandled error:'with make_context() as value:  raise ValueError('this exception is not handled')

打印結果

Normal: entering inside with statement: {}  exitinghandled ereor:entering Error: show example of handling an error exitingunhandled error:enteringexitingTraceback (most recent call last): File "test.py", line 30, in <module>   raise ValueError('this exception is not handled')   ValueError: this exception is not handled


嵌套上下文

使用nested()可以同時管理多個上下文。

import contextlib@contextlib.contextmanagerdef make_context(name):  print 'entering:', name  yield name  print 'exiting:', namewith contextlib.nested(make_context('A'), make_context('B'), make_context('C')) as (A, B,   C):  print 'inside with statement:', A, B, C

打印結果

entering: Aentering: Bentering: Cinside with statement: A B Cexiting: Cexiting: Bexiting: A

因為Python 2.7和以后的版本不贊成使用nested(),因為可以直接嵌套

import contextlib@contextlib.contextmanagerdef make_context(name):  print 'entering:', name  yield name  print 'exiting:', namewith make_context('A') as A, make_context('B') as B, make_context('C') as C:  print 'inside with statement:', A, B, C


關閉open的句柄

文件類支持上下文管理器, 但是有一些對象不支持。還有一些類使用close()方法但是不支持上下文管理器。我們使用closing()來為他創建一個上下文管理器。(類必須有close方法)

import contextlibclass Door(object):  def __init__(self):    print ' __init__()'      def close(self):    print ' close()'print 'Normal Example:'with contextlib.closing(Door()) as door:  print ' inside with statement'  print print 'Error handling example:'try:  with contextlib.closing(Door()) as door:    print ' raising from inside with statement'    raise RuntimeError('error message')except Exception, err:  print ' Had an error:', err

打印結果

Normal Example:  __init__()  inside with statement  close()Error handling example:  __init__()  raising from inside with statement  close()  Had an error: error message

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 吉木萨尔县| 磐安县| 巩留县| 威信县| 禹州市| 滕州市| 宁晋县| 关岭| 玉溪市| 丹棱县| 承德县| 泗水县| 沁水县| 沙洋县| 巫溪县| 象山县| 肥东县| 山丹县| 仙居县| 临潭县| 定远县| 抚顺县| 宿州市| 福建省| 上林县| 保靖县| 临清市| 施秉县| 防城港市| 龙山县| 汽车| 本溪市| 集安市| 读书| 长寿区| 灌阳县| 定边县| 全州县| 三都| 筠连县| 黎城县|