python 上下文管理

概念:实现了上下文协议的对象即为上下文管理器

上下文协议:__enter__、__exit__

作用:用于资源的获取和释放

open()函数的实现内部就是使用了以上两种方法

任何对象,只要正确实现了上下文管理,就可以用于with语句。
实现上下文管理是通过__enter__和__exit__这两个方法实现的,
也可以通过@contextmanager和closing函数实现

含有__enter__和__exit__方法的对象就是上下文管理器

class Foo(object):

def __init__(self):
    print('实例化一个对象')

def __enter__(self):
    print('进入')

def __exit__(self, exc_type, exc_val, exc_tb):
    print('退出')

obj = Foo()

with obj:
    print('正在执行')

上面代码执行结果为:

实例化一个对象
进入
正在执行
退出

with 上下文管理器:
     语句体

当with遇到上下文管理器,就会在执行语句体之前,先执行上下文管理器的__enter__方法,然后再执行语句体,执行完语句体后,最后执行__exit__方法

出现异常时,如果 exit 返回 False(默认不写返回值时,即为False),则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理

class Foo(object):

def __init__(self):
    print('实例化一个对象')

def __enter__(self):
    print('进入')

def __exit__(self, exc_type, exc_val, exc_tb):
    print('退出')
    # return True

obj = Foo()

with obj:
    raise ImportError
    print('正在执行')

调用上下文管理器的 enter 方法时;如果使用了 as 子句,则将 enter() 方法的返回值赋值给 as 子句中的目标

class Foo(object):

def __init__(self):
    print('实例化一个对象')

def __enter__(self):
    print('进入')
    # return self

def __exit__(self, exc_type, exc_val, exc_tb):
    print('退出')


with Foo() as obj:
     print(obj,type(obj))
     print('正在执行')

with 上下文管理器 as target:
代码语句体

with后面必须跟一个上下文管理器,如果使用了as,则是把上下文管理器的 enter() 方法的返回值赋值给 target,target 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)

使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄

with open("/tmp/foo.txt") as file:
    data = file.read()

比较try语句起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threading、decimal 等

进一步简化上下文管理 ----- Python 提供了一个 contextmanager 装饰器

from contextlib import contextmanager
class MyResource:
    def query(self):
        print('query data')

@contextmanager
def make_myresource():
    print('start to connect')
    yield MyResource()
    print('end connect')
    pass

被装饰器装饰的函数分为三部分:
with语句中的代码块执行前执行函数中yield之前代码
yield返回的内容复制给as之后的变量
with代码块执行完毕后执行函数中yield之后的代码

比如下方代码:

with make_myresource() as r:
    r.query()

执行结果是
start to connect
query data
end connect

数据库操作

from pymysql import *




class Database(object):
    def __init__(self,name,password):
        # 创建self.conn连接
        self.conn = connect(host='localhost',port=3306,database=str(name),user='tiger',password=str(password),charset='utf8')
        # 获得self.cursor对象
        self.cursor = self.conn.cursor()


    def __enter__(self):
        return self.cursor      # 返回self.cursor对象


    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cursor.close()     # 关闭self.cursor对象
        self.conn.close()       # 关闭self.conn连接




with Database('zzj_01','mysql') as db:
    db.execute(""" select * from students; """)     # 执行sql语句
    content = db.fetchall()                         # 获取数据
 #遍历获取到的数据,打印每一条数据
for info in content:
    print(info)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值