集团主站
欢迎来到成都达内官方网站!达内—美国上市公司 亿元级外企IT培训企业!
成都it培训哪家好
成都it培训哪家好
全国服务监督电话:400-111-8989  |   联系客服   |
当前位置:主页 > 培训课程 > Python >

成都python培训:Python上下文管理器和with用法

发布者: 成都达内     浏览次数:     发布时间:2020-03-21 10:52:37

导读:pythoners都知道有个关键字叫"with",它可以实现使用某些"临时"声明的对象,而之后"什么也不用管",这个用法在python中叫上下文管理器。本文带你快速入门上下文管理器和with用法。...

  导读:pythoners都知道有个关键字叫"with",它可以实现使用某些"临时"声明的对象,而之后"什么也不用管",这个用法在python中叫上下文管理器。本文带你快速入门上下文管理器和with用法。

  成都python培训:Python上下文管理器和with用法

  01 初识上下文管理器,英文context managers,在python官方文档中这样描述:

  上下文管理器是一个对象,它定义了在执行 with 语句时要建立的运行时上下文。 上下文管理器处理进入和退出所需运行时上下文以执行代码块。 通常使用 with 语句(在 with 语句中描述),但是也可以通过直接调用它们的方法来使用。

  那么可能还会有进一步的疑问:"上下文"又是什么呢?

  举个例子,在python中,写入文件的基本操作可能是这样的:

  1f = open('a.txt', 'w')2f.write('22')3f.close()

  如果考虑在文件操作期间可能会触发异常、造成文件不能关闭,那么比较安全的改进写法是:

  1f = open('a.txt', 'w')2try:3 f.write('22')4except:5 print('File eroor!')6finally:7 f.close()

  当使用with包装上下文管理器后,那么只需要这样:

  1with open('b.txt', 'w') as f:2 f.write('22')

  可能会有这样疑问,不就是节省了一行文件关闭的代码而已嘛,也没看出有多高效啊!

  这里先抛出结论:使用with管理上下文不仅可以在执行with语句体后自动执行退出操作(即__exit__方法定义语句),更重要的是能够在发生异常时,确保始终能执行退出操作、释放相应的资源。

  02 详解在PEP343(该PEP文档由python之父龟叔发起,最早在python2.5版本引入。如想了解更多关于PEP知识,可阅读PEP入门指南),对上下文管理器给出如下定义:

  上下文管理器是指提供了一对专门方法__enter __()和__exit __(),这些方法在with语句的主体进入和退出时被调用。在Python语言中添加了一个“ with”新语句,从而可以排除try / finally语句的标准用法。

  也就是说,如果某个类定义了__enter__、__exit__方法,允许在语句体执行前进入该上下文、执行后退出该上下文,那么这样的类就可以称作是上下文管理器对象。而且该用法可用作对try/finally的替代,以处理可能存在的异常。

  前面举了文件操作的with用法,说明文件操作的对象是一个上下文管理器对象,那么我们先来看下文件操作类来怎样定义的:

  1##_pyio.py 2### Context manager ### 3def __enter__(self): # That's a forward reference 4 """Context management protocol. Returns self (an instance of IOBase).""" 5 self._checkClosed() 6 return self 7 8def __exit__(self, *args): 9 """Context management protocol. Calls close()"""10 self.close()

  注:open()函数返回一个FileIO类对象,FileIO类继承自RawIOBase类,RawIOBase又继承自IOBase类,而IOBase类定义了__enter__和__exit__方法,因而是一个上下文管理器对象。

  同时,在IOBase类说明文档中,也给出了这样介绍:

  1"""IOBase also supports the :keyword:`with` statement. In this example,2fp is closed after the suite of the with statement is complete:34with open('spam.txt', 'r') as fp:5 fp.write('Spam and eggs!')"""

  再举个例子,在python并发之concurrent快速入门一文中,对比多线程和多进程的并发操作时,也使用了with包装上下文管理器的用法:

  1from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor2def multi_thread():3 with ThreadPoolExecutor() as executor:4 return list(executor.map(is_prime, PRIMES))56def multi_process():7 with ProcessPoolExecutor() as executor:8 return list(executor.map(is_prime, PRIMES))

  那么有理由相信,concurrent.futures类肯定也定义了__enter__和__exit__方法,具体如下:

  1##_base.py2def __enter__(self):3 return self45def __exit__(self, exc_type, exc_val, exc_tb):6 self.shutdown(wait=True)7 return False

  注:ThreadPoolExecutor和ProcessPoolExecutor两个类均继承自Executor类,而Excutor类是一个上下文管理器对象。

  需补充说明的是,正如上述示例代码给出的那样,__exit__()方法默认接收3个参数:exc_type、exc_val、exc_tb,如果with语句体发生异常,则3个参数分别赋值为type(error)、str(error)、error.__traceback__,否则均为None。

  至此,我们可以得出这样的结论:一个上下文管理器对象是指定义了__enter__和__exit__方法的类对象;反之,定义了__enter__和__exit__方法的类可以应用with包装实现上下文管理器用法。

  应用with包装上下文管理器时:执行with语句生成一个实例对象时,自动调用__enter__方法创建一个适用于上下文环境的类对象,完毕后无论是否触发异常都会调用__exit__方法执行退出操作。

  03 实战实际上,上下文管理器常适用于带有资源管理的操作,如前面例子中给出的文件操作和并发操作。这里,我们举一个操作数据库的例子,实现一个简单的打开数据库类。

  1import pymysql 2class OpenMySQL(object): 3 def __init__(self, db): 4 self.conn = pymysql.connect(host="localhost", user="root", password="123456", db=db, charset='utf8') 5 6 def __enter__(self): 7 return self.conn.cursor() 8 9 def __exit__(self, exc_type, exc_val, exc_tb):10 self.conn.commit()11 self.conn.close()1213if __name__ == '__main__':14 with OpenMySQL('mytest') as sql:15 sql_insert = 'insert into tbtest values (2);'16 sql.execute(sql_insert)

  代码功能执行正常,且相比于基本的数据库connect()--commit()--close()操作流程来说,要优雅许多。

  注:写完例子后查阅源码发现pymysql.connect方法返回对象本身就是一个上下文管理器对象……。但仅仅用于举例的话,这也足以说明with包装上下文管理器的用法了。

  04 总结本文对python中上下文管理器和with用法进行了简单介绍,包括:

  上下文管理器是一个实现了__enter__、__exit__魔法方法的类对象

  定义了__enter__、__exit__方法的类对象即可用作上下文管理器

  上下文管理器通常使用with语句实现

  with语句可实现简洁版的try/finally替代用法

(责任编辑:范老师)
最新开班
  • 成都Java培训班
    免费试听名额发放中...
  • 成都C++培训班
    免费试听名额发放中...
  • 成都PHP培训班
    免费试听名额发放中...
  • 成都网络工程培训班
    免费试听名额发放中...
  • 成都Unity3D培训班
    免费试听名额发放中...
  • 成都大数据培训班
    免费试听名额发放中...
  • 成都uid培训班
    免费试听名额发放中...
  • 成都会计培训班
    免费试听名额发放中...
  • 成都Python培训班
    免费试听名额发放中...
  • 成都嵌入式培训班
    免费试听名额发放中...
  • 成都web培训班
    免费试听名额发放中...
  • 成都软件测试培训班
    免费试听名额发放中...
在线留言
提交

校区地址:成都市锦江区东大街紫东楼端35号明宇金融广场19楼1906室

联系电话:400-111-8989

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市高新区奥克斯广场蜀锦路209号一楼商铺

联系电话:400-111-8989

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都锦江区东大街芷泉街229号东方广场C座3楼303

联系电话:400-111-8989

公交路线:芷泉街(188路;115路;515路;236路;505路;501路;84路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市武侯区佳灵路3号红牌楼广场2号写字楼11楼1115号

联系电话:400-111-8989

公交路线:红牌楼东(11路;92路;100路;111路;139路;g28路;快速公交K1/K2) 地铁路线:红牌楼站(地铁3号线)

校区地址:成都市锦江区红星路二段70号四川日报大厦502-2

联系电话:400-111-8989

公交路线:市二医院站(6路;49路;102路;5路;37路;g92路;) 地铁路线:地铁市二医院(地铁3号线)

校区地址:成都市锦江区东大街芷泉段229号东方广场C座16层

联系电话:400-111-8989

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:四川省成都市武侯区高新科技孵化园9号园区E座7楼

联系电话:400-111-8989

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

了解达内动态
关注成都达内教育公众号

首页 | 关于达内 | 课程中心 | 专家师资 | 视频教程 | 学员空间 | 校企合作 | 新闻资讯 | 就业指导 | 网站地图

2016-2025 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56 蜀ICP备18021046号-3