最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2016年06月28日 15:36:09   作者:cangmean  
Python中一些內(nèi)建對(duì)象有了上下文管理器的支持,于是可以使用with語(yǔ)句來(lái)實(shí)現(xiàn)自動(dòng)的文件打開(kāi)關(guān)閉以及線(xiàn)程操作等,這里我們就從根基上來(lái)詳解Python中contextlib上下文管理模塊的用法

咱們用的os模塊,讀取文件的時(shí)候,其實(shí)他是含有__enter__ __exit__ 。  一個(gè)是with觸發(fā)的時(shí)候,一個(gè)是退出的時(shí)候。

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

那咱們自己再實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)的可以with的類(lèi)。 我個(gè)人寫(xiě)python的時(shí)候,喜歡針對(duì)一些需要有關(guān)閉邏輯的代碼,構(gòu)造成with的模式 。 

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

contextlib是個(gè)比with優(yōu)美的東西,也是提供上下文機(jī)制的模塊,它是通過(guò)Generator裝飾器實(shí)現(xiàn)的,不再是采用__enter__和__exit__。contextlib中的contextmanager作為裝飾器來(lái)提供一種針對(duì)函數(shù)級(jí)別的上下文管理機(jī)制。

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

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

from contextlib import contextmanager
from random import random
 
DEFAULT_EXPIRES = 15
DEFAULT_RETRIES = 5
 
@contextmanager
def 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

一個(gè)上下文管理器通過(guò)with聲明激活, 而且API包含兩個(gè)方法。__enter__()方法運(yùn)行執(zhí)行流進(jìn)入到with代碼塊內(nèi)。他返回一個(gè)對(duì)象共上下文使用。當(dāng)執(zhí)行流離開(kāi)with塊時(shí),__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.'

打印結(jié)果

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

執(zhí)行上下文管理器時(shí)會(huì)調(diào)用__enter__離開(kāi)時(shí)調(diào)用__exit__。

__enter__能返回任意對(duì)象,聯(lián)合一個(gè)指定名字于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()

打印結(jié)果

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

如果上下文管理器能處理異常,__exit__()應(yīng)該返回一個(gè)True值表明這個(gè)異常不需要傳播,返回False異常會(huì)在執(zhí)行__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_error

with Context(True):
  raise RuntimeError('error message handled')

print

with Context(False):
  raise RuntimeError('error message propagated')

打印結(jié)果

__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


從生成器到上下文管理器

創(chuàng)建上下文管理的傳統(tǒng)方法,通過(guò)編寫(xiě)一個(gè)類(lèi)與__enter__()和__exit__()方法,并不困難。但有時(shí)比你需要的開(kāi)銷(xiāo)只是管理一個(gè)微不足道的上下文。在這類(lèi)情況下,您可以使用contextmanager() decorat or 生成器函數(shù)轉(zhuǎn)換成一個(gè)上下文管理器。

import contextlib

@contextlib.contextmanager
def 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
  
print
print 'handled ereor:'

with make_context() as value:
  raise RuntimeError('show example of handling an error')

print
print 'unhandled error:'

with make_context() as value:
  raise ValueError('this exception is not handled')

打印結(jié)果

Normal:
 entering
 inside with statement: {}
  exiting

handled ereor:
entering
 Error: show example of handling an error
 exiting

unhandled error:
entering
exiting
Traceback (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()可以同時(shí)管理多個(gè)上下文。

import contextlib

@contextlib.contextmanager
def make_context(name):
  print 'entering:', name
  yield name
  print 'exiting:', name

with contextlib.nested(make_context('A'), make_context('B'), make_context('C')) as (A, B,   C):
  print 'inside with statement:', A, B, C

打印結(jié)果

entering: A
entering: B
entering: C
inside with statement: A B C
exiting: C
exiting: B
exiting: A

因?yàn)镻ython 2.7和以后的版本不贊成使用nested(),因?yàn)榭梢灾苯忧短?/p>

import contextlib

@contextlib.contextmanager
def make_context(name):
  print 'entering:', name
  yield name
  print 'exiting:', name

with make_context('A') as A, make_context('B') as B, make_context('C') as C:
  print 'inside with statement:', A, B, C


關(guān)閉open的句柄

文件類(lèi)支持上下文管理器, 但是有一些對(duì)象不支持。還有一些類(lèi)使用close()方法但是不支持上下文管理器。我們使用closing()來(lái)為他創(chuàng)建一個(gè)上下文管理器。(類(lèi)必須有close方法)

import contextlib


class 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

打印結(jié)果

Normal Example:
  __init__()
  inside with statement
  close()

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

相關(guān)文章

  • typing.Dict和Dict的區(qū)別及它們?cè)赑ython中的用途小結(jié)

    typing.Dict和Dict的區(qū)別及它們?cè)赑ython中的用途小結(jié)

    當(dāng)在 Python 函數(shù)中聲明一個(gè) dictionary 作為參數(shù)時(shí),我們一般會(huì)把 key 和 value 的數(shù)據(jù)類(lèi)型聲明為全局變量,而不是局部變量。,這篇文章主要介紹了typing.Dict和Dict的區(qū)別及它們?cè)赑ython中的用途小結(jié),需要的朋友可以參考下
    2023-06-06
  • Pygame改編飛機(jī)大戰(zhàn)制作兔子接月餅游戲

    Pygame改編飛機(jī)大戰(zhàn)制作兔子接月餅游戲

    一年中秋又快到了,今年加入了Python的學(xué)習(xí)行列,得益于Python的開(kāi)發(fā)效率和易讀性,網(wǎng)上寫(xiě)文章的次數(shù)多了起來(lái),既然是中秋節(jié)那肯定要搞個(gè)應(yīng)景的游戲才行
    2022-09-09
  • Python3如何使用range函數(shù)替代xrange函數(shù)

    Python3如何使用range函數(shù)替代xrange函數(shù)

    這篇文章主要介紹了Python3如何使用range函數(shù)替代xrange函數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 詳解Python如何巧妙實(shí)現(xiàn)數(shù)學(xué)階乘n!

    詳解Python如何巧妙實(shí)現(xiàn)數(shù)學(xué)階乘n!

    一個(gè)正整數(shù)的階乘(factorial)是所有小于及等于該數(shù)的正整數(shù)的積,并且0的階乘為1。自然數(shù)n的階乘寫(xiě)作n!,本文就給大家介紹如何使用python和第三方庫(kù)來(lái)實(shí)現(xiàn)數(shù)學(xué)運(yùn)算中的階乘以及階乘累計(jì)求和
    2023-03-03
  • Python統(tǒng)計(jì)不同整數(shù)的出現(xiàn)次數(shù)的三種方法

    Python統(tǒng)計(jì)不同整數(shù)的出現(xiàn)次數(shù)的三種方法

    在數(shù)據(jù)處理和分析領(lǐng)域,統(tǒng)計(jì)不同整數(shù)的出現(xiàn)次數(shù)是一個(gè)常見(jiàn)需求,無(wú)論是清洗日志數(shù)據(jù)、分析用戶(hù)行為,還是處理實(shí)驗(yàn)觀(guān)測(cè)值,我們都需要快速準(zhǔn)確地獲取不同整數(shù)的數(shù)量,本文將用通俗的語(yǔ)言,結(jié)合Python代碼示例,為你系統(tǒng)講解三種主流解決方案,需要的朋友可以參考下
    2025-04-04
  • Python被遠(yuǎn)程主機(jī)強(qiáng)制關(guān)閉后自動(dòng)重新運(yùn)行進(jìn)程的示例

    Python被遠(yuǎn)程主機(jī)強(qiáng)制關(guān)閉后自動(dòng)重新運(yùn)行進(jìn)程的示例

    要實(shí)現(xiàn)Python程序在被遠(yuǎn)程主機(jī)強(qiáng)制關(guān)閉后能夠自動(dòng)重新運(yùn)行,我們可以采用幾種方法,但最直接且常用的方法之一是結(jié)合操作系統(tǒng)級(jí)的工具或腳本,這篇文章主要介紹了Python被遠(yuǎn)程主機(jī)強(qiáng)制關(guān)閉后怎么自動(dòng)重新運(yùn)行進(jìn)程,需要的朋友可以參考下
    2024-08-08
  • python自動(dòng)化生成IOS的圖標(biāo)

    python自動(dòng)化生成IOS的圖標(biāo)

    這篇文章主要為大家詳細(xì)介紹了python如何自動(dòng)化生成IOS的圖標(biāo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Python操作數(shù)據(jù)庫(kù)之?dāng)?shù)據(jù)庫(kù)編程接口

    Python操作數(shù)據(jù)庫(kù)之?dāng)?shù)據(jù)庫(kù)編程接口

    這篇文章主要介紹了Python操作數(shù)據(jù)庫(kù)之?dāng)?shù)據(jù)庫(kù)編程接口,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-06-06
  • 詳解Python?Selenium如何獲取鼠標(biāo)指向的元素

    詳解Python?Selenium如何獲取鼠標(biāo)指向的元素

    這篇文章主要介紹了如何通過(guò)Selenium獲取當(dāng)前鼠標(biāo)指向的元素,本文方法的核心,是借助JavaScript的事件(event)來(lái)獲取鼠標(biāo)所在的元素,感興趣的可以試一試
    2022-03-03
  • Python守護(hù)進(jìn)程用法實(shí)例分析

    Python守護(hù)進(jìn)程用法實(shí)例分析

    這篇文章主要介紹了Python守護(hù)進(jìn)程用法,實(shí)例分析了Python守護(hù)進(jìn)程的功能及使用方法,需要的朋友可以參考下
    2015-06-06

最新評(píng)論

卓资县| 扎鲁特旗| 秦皇岛市| 清涧县| 宜兰市| 望谟县| 岳阳市| 徐水县| 易门县| 双鸭山市| 甘德县| 万安县| 玉溪市| 安泽县| 夏津县| 商洛市| 诸暨市| 玉屏| 兖州市| 读书| 陈巴尔虎旗| 郓城县| 万盛区| 天峻县| 云林县| 潜江市| 武城县| 滕州市| 罗平县| 灌阳县| 洞口县| 商河县| 仁寿县| 古丈县| 宜都市| 高台县| 抚远县| 德兴市| 宁海县| 祁门县| 兰坪|