Effective Python 讀書筆記: 第43條: 考慮以contextlib和with語句來改寫可複用的try/finally代碼

# -*- encoding: utf-8 -*-

from contextlib import contextmanager
import logging

'''
第43條: 考慮以contextlib和with語句來改寫可複用的try/finally代碼

關鍵:
1 with語句
作用: 進行文件關閉,資源清理,鎖的獲取與釋放等
支持with: 
方式1:用contextlib模塊處理自己編寫的對象和函數
    提供了contextmanager的裝飾器
方式2: 定義一個類,提供__enter__和__exit__的特殊方法

2 使用帶有目標的with語句
用法: 傳給with語句的那個情境管理器,本身可以返回一個對象
with中的as: 指定一個局部變量,會把情境管理器的對象,賦給這個局部變量
應用場景:
打開文件,as指定變量接收open返回的文件句柄

3 情境管理器
用法:在情境管理器中通過yield語句返回值,然後另自己的函數把該值提供給
as指定的目標變量
用法示例:
@contextmanager
def logLevel(level, name):
    logger = logging.getLogger(name)
    oldLevel = logger.getEffectiveLevel()
    logger.setLevel(level)
    try:
        yield logger
    finally:
        logger.setLevel(oldLevel)

with logLevel(logging.DEBUG, 'myLog') as logger:
    logger.debug('I like python.')


4 總結
contextlib.contextmanager裝飾器可以修飾函數,來讓函數支持with語句,
只需要在該函數中原來return返回的地方修改爲yield, 則as關鍵字就可以將
返回的結果賦值給一個局部變量。


參考:
Effectiv Python 編寫高質量Python代碼的59個有效方法
'''
def func():
    logging.debug('debug data')
    logging.error('error data')
    logging.debug('debug data')


@contextmanager
def debugLogging(level):
    logger = logging.getLogger()
    oldLevel = logger.getEffectiveLevel()
    logger.setLevel(level)
    try:
        yield
    finally:
        logger.setLevel(oldLevel)


def useContextManager():
    with debugLogging(logging.DEBUG):
        print "Inside"
        func()
    print "After"
    func()

    with logLevel(logging.DEBUG, 'myLog') as logger:
        logger.debug('I like python.')
        logging.debug('This will not print.')
    logger = logging.getLogger('myLog')
    logger.debug('Debug will do not print.')
    logger.error('Error will print.')

def useWith():
    with open('/tmp/data.txt', 'w') as handle:
        handle.write("I like python.")


@contextmanager
def logLevel(level, name):
    logger = logging.getLogger(name)
    oldLevel = logger.getEffectiveLevel()
    logger.setLevel(level)
    try:
        yield logger
    finally:
        logger.setLevel(oldLevel)


def process():
    useContextManager()
    useWith()


if __name__ == "__main__":
    process() 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章