欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

那咱們自己再實(shí)現(xiàn)一個標(biāo)準(zhǔn)的可以with的類。 我個人寫python的時候,喜歡針對一些需要有關(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是個比with優(yōu)美的東西,也是提供上下文機(jī)制的模塊,它是通過Generator裝飾器實(shí)現(xiàn)的,不再是采用__enter__和__exit__。contextlib中的contextmanager作為裝飾器來提供一種針對函數(shù)級別的上下文管理機(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

我這里再貼下我上次寫的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

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

打印結(jié)果

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

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

__enter__能返回任意對象,聯(lián)合一個指定名字于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)該返回一個True值表明這個異常不需要傳播,返回False異常會在執(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)方法,通過編寫一個類與__enter__()和__exit__()方法,并不困難。但有時比你需要的開銷只是管理一個微不足道的上下文。在這類情況下,您可以使用contextmanager() decorat or 生成器函數(shù)轉(zhuǎn)換成一個上下文管理器。

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()可以同時管理多個上下文。

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的句柄

文件類支持上下文管理器, 但是有一些對象不支持。還有一些類使用close()方法但是不支持上下文管理器。我們使用closing()來為他創(chuàng)建一個上下文管理器。(類必須有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)文章

  • Python基于traceback模塊獲取異常信息

    Python基于traceback模塊獲取異常信息

    這篇文章主要介紹了Python基于traceback模塊獲取異常信息,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 深入理解Python中的super()方法

    深入理解Python中的super()方法

    super 是用來解決多重繼承問題的,直接用類名調(diào)用父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查找順序(MRO)、重復(fù)調(diào)用(鉆石繼承)等種種問題。這篇文章主要給大家介紹了關(guān)于Python中super()方法的相關(guān)資料,需要的朋友可以參考下。
    2017-11-11
  • python 通過類中一個方法獲取另一個方法變量的實(shí)例

    python 通過類中一個方法獲取另一個方法變量的實(shí)例

    今天小編就為大家分享一篇python 通過類中一個方法獲取另一個方法變量的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • Python2和Python3中urllib庫中urlencode的使用注意事項(xiàng)

    Python2和Python3中urllib庫中urlencode的使用注意事項(xiàng)

    這篇文章主要介紹了Python2和Python3中urllib庫中urlencode的使用注意事項(xiàng),非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-11-11
  • Python詳解復(fù)雜CSV文件處理方法

    Python詳解復(fù)雜CSV文件處理方法

    這篇文章主要介紹了Python數(shù)據(jù)讀寫之Python讀寫CSV文件,CSV即逗號分隔值,一種以逗號分隔按行存儲的文本文件,所有的值都表現(xiàn)為字符串類型,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-07-07
  • 在PyCharm的 Terminal(終端)切換Python版本的方法

    在PyCharm的 Terminal(終端)切換Python版本的方法

    這篇文章主要介紹了在PyCharm的 Terminal(終端)切換Python版本的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python出現(xiàn)segfault錯誤解決方法

    Python出現(xiàn)segfault錯誤解決方法

    這篇文章主要介紹了Python出現(xiàn)segfault錯誤解決方法,分析了系統(tǒng)日志提示segfault錯誤的原因與對應(yīng)的解決方法,需要的朋友可以參考下
    2016-04-04
  • python 梯度法求解函數(shù)極值的實(shí)例

    python 梯度法求解函數(shù)極值的實(shí)例

    今天小編就為大家分享一篇python 梯度法求解函數(shù)極值的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • python3實(shí)現(xiàn)爬取淘寶美食代碼分享

    python3實(shí)現(xiàn)爬取淘寶美食代碼分享

    本文給大家分享的是如何使用python3來爬取淘寶美食圖片標(biāo)題等信息的方法和代碼,有需要的小伙伴可以參考下
    2018-09-09
  • python/Matplotlib繪制復(fù)變函數(shù)圖像教程

    python/Matplotlib繪制復(fù)變函數(shù)圖像教程

    今天小編就為大家分享一篇python/Matplotlib繪制復(fù)變函數(shù)圖像教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11

最新評論