例子一

首先来看一段代码:

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('正在执行')

上面代码执行结果为:

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

结论1

我们知道,实例化Foo,得到obj对象,会执行Foo的__init__方法,也就是打印了第一句;

按照,程序从上至下执行,应该会打印“正在执行”才对,为什么会在它之前先打印了进入,在它之后打印了退出呢?

因为我们在定义Foo时,定义了__enter__和__exit__方法,那么我们实例化的对象obj就是一个上下文管理器,

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

with 上下文管理器:
 语句体

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

这也就是为什么会出现文章开头的情况的原因。

例子二

再看看这段代码:

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('正在执行')

结果如下:

把上面代码中我们注释掉的那一行代码取消注释,结果如下

我们会发现,虽然我们故意在语句体中抛出一个错误,按照正常情况,执行到报错地方就不会执行了,而__exit__是在语句体执行完之后执行的,但还是执行了__exit__方法;当我们在__exit__中给一个返回值为Ture时,就会忽略错误。

结论2

所有我们可以发现

with语句类似

  try :

  except:

  finally:

的功能:但是with语句更简洁。而且更安全。代码量更少。

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

例子三

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('正在执行')

把上面代码中我们注释掉的那一行代码取消注释,结果如下

结论

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

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

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

例子四

我们经常会看到这样的代码:

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

结论

这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄。如果使用传统的 try/finally 范式,则要使用类似如下代码:

somefile = open(r'somefileName')
try:
for line in somefile:
print line
# ...more code
finally:
somefile.close()

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

补充

with只能配合上下文管理器使用,常见的上下文管理器有

file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore

浅淡python中的with,上下文管理器的更多相关文章

  1. Python进阶——什么是上下文管理器?

    在 Python 开发中,我们经常会使用到 with 语法块,例如在读写文件时,保证文件描述符的正确关闭,避免资源泄露问题. 你有没有思考过, with 背后是如何实现的?我们常常听到的上下文管理器究 ...

  2. Python: 浅淡Python中的属性(property)

    起源:项目过程中需要研究youtube_dl这个开源组件,翻阅其中对类的使用,对比c#及Delphi中实现,感觉Python属性机制挺有意思.区别与高级编程语言之单一入口,在类之属性这一方面,它随意的 ...

  3. python2.7高级编程 笔记一(Python中的with语句与上下文管理器学习总结)

    0.关于上下文管理器上下文管理器是可以在with语句中使用,拥有__enter__和__exit__方法的对象. with manager as var: do_something(var) 相当于以 ...

  4. asyncio之异步上下文管理器

    异步上下文管理器 前面文章我们提到了上下文管理器,但是这个上下文管理器只适用于同步代码,不能用于异步代码(async def形式),不过不用担心今天我们就来讨论在异步中如何使用上下文管理器. 特别提醒 ...

  5. (转)contextlib — 上下文管理器工具

    原文:https://pythoncaff.com/docs/pymotw/contextlib-context-manager-tool/95 这是一篇社区协同翻译的文章,你可以点击右边区块信息里的 ...

  6. Python中的上下文管理器和with语句

    Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先, ...

  7. 深入理解 Python 中的上下文管理器

    提示:前面的内容较为基础,重点知识在后半段. with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with open ,这就是一个上下文管 ...

  8. (转)Python中的上下文管理器和Tornado对其的巧妙应用

    原文:https://www.binss.me/blog/the-context-manager-of-python-and-the-applications-in-tornado/ 上下文是什么? ...

  9. python中实现上下文管理器的两种方法

    上下文管理器: python中实现了__enter__和__exit__方法的对象就可以称之为上下文管理器 实现方法一举例: def File(object): def __init__(self, ...

随机推荐

  1. 读取指定文件夹下的全部文件,可通过正则进行过滤,返回文件路径数组 -- 基于node的一个函数

    var fs = require('fs'); // 模板文件夹路径 var templateDirectory = '../src'; //相对于当前文件的相对路径 //var templateDi ...

  2. 第03章-VTK系统概述(1)

    [译者:这个系列教程是以Kitware公司出版的<VTK User's Guide -11th edition>一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934- ...

  3. NYOJ 480 Fibonacci Again!

    Fibonacci Again! 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 求第n个斐波那契数是否是一个素数,n为整数 f[n]=f[n-1]+f[n-2] ( ...

  4. 配置SQL Server on Linux(1)

    1. 背景 SQL Server一般是在安装过程中进行相关的配置,安装完成之后,再去修改有一些配置就比较麻烦,比如更改SQL Server实例级别的排序规则.但在Linux下,安装过程并没有很多可以配 ...

  5. web.config中配置数据库(多数据)连接的两种方式

    这是我的第一篇文章,既然是第一篇了,那就从最基础的只是说起--web.config中配置数据库连接. 网上有很多这方面的资料,但发现并没有一篇从头到位很清楚明了说完的,今天就把我的整理写在这里吧. 在 ...

  6. Android开发——导入github安卓项目源码

    之前在Github上看见其他人的安卓项目源码,便是想下载源码来学习学习,但是下载之后一直导入失败,经过了漫长的摸索终于是成功了,便是分享一下经验 首先进入Github官网,找到想要学习的安卓源码 右上 ...

  7. DotNetCore跨平台~功能测试TestHost的使用

    回到目录 之前写了关于自动化测试的相关文章,包括gitlab,unittest,jenkins pipeline等,基于都是功能点的测试,当我们的框架或者业务修改之后,需要走一篇自动化测试,以此来保证 ...

  8. 关于《ASP.NET MVC企业级实战》

    大家好,我的书<ASP.NET MVC企业级实战>已经出版啦,感谢大家过去的关注与支持!前言部分,出版的时候漏了部分内容,我这里将其贴出来. 本书提供源码和教学PPT课件!(源码在书中第3 ...

  9. C++ 头文件系列(stdexcept)

    预定义异常类 这个头文件包含的内容非常简单,只包含9个异常类,均从exception类派生,因此我们用三张图来描述: 这里仅解释两点: overflow : 指值的大小超过 整型 变量能表示的范围,即 ...

  10. Jrebel简单的热部署一个web工程

    前言:博主最近在做Hybris开发,漫长的启动时间大大的拖累了项目的进度,而Jrebel的出现就是为了减少项目重启的时间或者说修改了代码后直接不用重启就可以看到修改的结果,但是Hybris的部署一直没 ...