利用上下文管理器,可以让代码更加优雅简便。固然,上下文的管理器的作用不止于此,它内部的实现机制,能很好的处置惩罚代码非常,提拔代码的复用性
1、先看看最简单的例子,with语句
# 创建一个文件写入字符串“Python”f = open('123.txt', 'w')f.write("python")f.close()# 利用with语句调用上下文实现文件写入利用with open('123.txt', 'w') as f: f.write('python')with语句的作用:
可以主动管理上下文资源,岂论什么缘故原由跳出with块,都能确保文件精确的关闭,以此来到达释放资源的目标。
2、什么是上下文管理器?
上下文是 context 直译的叫法,在步伐中用来表示代码实行过程中所处的前后情况,好比在文件利用时,文件须要打开关闭,而文件读写利用就处于文件利用的上下文情况中;
上下文管理器,上下文管理器是指在一段代码实行之前,实行一些预处置惩罚的工作,代码实行之后再实行一些清算工作。
上下文管理器中有enter()和 exit() 两个方法,enter()方法在实行 with 背面的语句时实行,一样寻常用来处置惩罚利用前的内容,好比一些创建对象,初始化等; exit() 方法在 with 内的代码实行完毕后实行,一样寻常用来处置惩罚一些善后收尾工作,好比文件的关闭,数据库的关闭等。
3、上下文管理器的原理过程如下:
调用enter()方法,举行预处置惩罚利用
实行用户利用
调用 exit() 方法,完成清算利用
4、上下文管理器的应用场景:
资源管理功能,即文件处置惩罚、网络毗连、数据库毗连等利用时须要关闭资源。
也可以在代码实行前后增长功能,类似于装饰器,好比代码之前做权限验证等。
4.1 数据库毗连
import pymysqlclass DBConnection(object): def __init__(self,ip,user,passwd,db): self.ip = ip self.user = user self.passwd = passwd self.db = db def __enter__(self): self.conn = pymysql.connect(self.ip, user=self.user, passwd=self.passwd, db=self.db) self.cur = conn.cursor() return self.cur def __exit__(self, exc_type, exc_val, exc_tb): self.cur.close() self.conn.close()with DBConnection('192.168.121.xxx', user="xxx", passwd="123456", db="xxx") as cur: cur.execute("select * from studnet;") result = cur.fetchall() print(result)完成DBConnection这个类,每次毗连数据库时,只要简单的调用with语句即可,不须要关心数据库的关闭、非常等
4.2、上下文管理器的非常处置惩罚
class MyOpen(object): """自界说上下文管理类""" def __init__(self, file, mode): self._file = file self._mode = mode def __enter__(self): self._handle = open(self._file, self._mode) return self._handle def __exit__(self, exc_type, exc_val, exc_tb): # print('Type: ', exc_type) # print('Value:', exc_val) # print('TreacBack:', exc_tb) self._handle.close() print("非常已被处置惩罚") return True# 读的模式打开文件,举行写利用,不支持with MyOpen('123.txt', 'r') as f: f.write('python')#输出:非常已被处置惩罚with 语法不仅可以简化资源利用的后续扫除利用,还可以取代 try/finally 举行非常处置惩罚
当with中实行的语句发生非常时,非常信息会被发送到 exit()方法的参数中, exit() 方法有如下三个参数:
exc_type : 非常范例
exc_val : 非常值
exc_tb : 非常回溯追踪
这三个参数都与非常有关,with语句会把非常的exc_type ,exc_val 和exc_tb转达给 exit() 方法,它让exit() 方法来处置惩罚非常 ,假如exit()返回的是True,那么这个非常就被忽略,并按照我们界说的方式举行抛出。假如exit()返回的是True以外的任何东西,那么这个非常将被with语句抛出。
4.3、通过contextlib实现
python内置了contextlib这个模块用于实现上下文管理器,它是通过天生器yield实现的,这个模块让我们不必创建类和enter和exit了。
from contextlib import contextmanager@contextmanagerdef diy_open(filename, **kwargs): f = open(filename, **kwargs) try: yield f finally: f.close()with diy_open('test.txt', encoding='utf-8') as f: print(f.readlines()) |