# 上下文管理器的用法
# 1.资源清理************************************************************************
# 数据库连接
import pymysql
class DBConnection(object):
def __init__(self,user=None,password=None,dbname=None,host='localhost'):
self.user = user
self.password = password
self.host = host
self.dbname = dbname
def __enter__(self):
self.connection = pymysql.connect(self.host,self.user,self.password,self.dbname )
return self.connection.cursor()
def __exit__(self, exc_type, exc_val, exc_tb):
self.connection.close()
with DBConnection(user='root',password='root',dbname='test2') as db: #as 后边的变量接受__enter__返回的对象
db.execute('select 1+1')
a = db.fetchall()
print(a)
# 2.避免重复(传播异常)************************************************************************
class BubbleException(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val:
print('bubbling up eception :%s' %exc_val)
return False
# with BubbleException():
# a = 5+5
# with BubbleException():
# a = 5/0
# 2.避免重复(终止异常)************************************************************************
class SupressException(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val:
print('supressing up eception :%s' %exc_val)
return True #尽量不要这么做
# 上述行为与以下示例是相似的
try:
['do something']
except:
pass
# with SupressException():
# a = 5+5
# print(a)
#
# with SupressException():
# a = 5/0
# print(a)
# 2.避免重复(处理特定异常的类)************************************************************************
class HandleValueError(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if issubclass(exc_type,ValueError):
return True
return False
#特定的异常阻止抛出
with HandleValueError():
raise ValueError('wrong value')
#剩余的异常继续抛出
# with HandleValueError():
# raise TypeError('type error')
# 2.避免重复(不包括的子类,只捕获一个给定的异常类,不捕获他的子类)************************************************************************
class ValueErrorSubclass(ValueError):
pass
class HandleValueError(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type == ValueError:
return True
return False
with HandleValueError():
pass
# raise ValueErrorSubclass('value error subclass')
# 3.更简单的用法************************************************************************
import contextlib
# @contextlib.contextmanager 装饰简单函数,将函数转换为上下文管理器类
from contextlib import contextmanager
@contextmanager
def file_open(path):
try:
f_obj = open(path,"w")
yield f_obj
except OSError:
print("We had an error!")
finally:
print("Closing file")
f_obj.close()
# with file_open("test.txt") as fobj:
# fobj.write("Testing context managers")