# -*- 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()