什么是上下文管理器

基本语法

with EXPR as VAR:
BLOCK

概念

  • 上下文表达式:with open('test.txt') as f:
  • 上下文管理器:open('test.txt')
  • f 不是上下文管理器,应该是资源对象

作用

  • with语句就是简洁版的try/finally语句
  • 代码块前后必然会执行的内容

原理

上下文管理器是内部实现了__enter__和__exit__方法的对象

class Foo:
def __init__(self):
print("实例化一个对象") def __enter__(self):
print("进入")
return self def __exit__(self, exc_type, exc_val, exc_tb):
print("退出")
return True def func(self):
print("被执行的方法") with Foo() as f:
f.func() >>>实例化一个对象
>>>进入
>>>被执行的方法
>>>退出
  • __enter__方法说明

    上下文管理器的__enter__方法是可以带返回值的,默认返回None,这个返回值通过with...as...中的 as 赋给它后面的那个变量,所以 with EXPR as VAR 就是将EXPR对象__enter__方法的返回值赋给 VAR,VAR可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。
    
    with...as...并非固定组合,单独使用with...也是可以的,上下文管理器的__enter__方法还是正常执行,只是这个返回值并没有赋给一个变量,with下面的代码块也不能使用这个返回值。
  • __exit__方法说明

    上下文管理器的__exit__方法接收3个参数exc_type、exc_val、exc_tb,如果代码块BLOCK发生了异常e并退出,这3个参数分别为type(e)、str(e)、e.__traceback__,否则都为None。
    
    同样__exit__方法也是可以带返回值的,这个返回值应该是一个布尔类型True或False,默认为None(即False)。如果为False,异常会被抛出,用户需要进行异常处理。如果为True,则表示忽略该异常。

上下文管理器的使用

异常处理

​ 处理异常,通常都是使用 try...execept.. 来捕获处理的。这样做一个不好的地方是,在代码的主逻辑里,会有大量的异常处理代理,这会很大的影响我们的可读性。

好一点的做法呢,可以使用 with 将异常的处理隐藏起来。

仍然是以上面的代码为例,我们将1/0 这个一定会抛出异常的代码写在 func

__exit__ 函数的三个参数

  • exc_type:异常类型
  • exc_val:异常值
  • exc_tb:异常的错误栈信息
class Foo:
def __init__(self):
print("实例化一个对象") def __enter__(self):
print("进入")
return self def __exit__(self, exc_type, exc_val, exc_tb):
import traceback
if exc_val:
print("异常类型:",exc_type)
print("异常值:",exc_val)
traceback.print_tb(exc_tb,-1)#打印最开始的错误信息,可设置错误栈数以及写入文件
print("退出")
return True def func(self):
print(1 / 0)
print("被执行的方法") with Foo() as f:
f.func() ---------------------------------------------
实例化一个对象
进入
File "F:/PyProgram/test98/test1.py", line 62, in func
print(1 / 0)
异常类型: <class 'ZeroDivisionError'>
异常值: division by zero
退出

资源管理

​ 在我们日常使用场景中,经常会操作一些资源,比如文件对象、数据库连接、Socket连接等,资源操作完了之后,不管操作的成功与否,最重要的事情就是关闭该资源,否则资源打开太多而没有关闭,程序会报错 。

常见的上下文管理器

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

理解并使用 contextlib

​ Python还提供了一个contextmanager装饰器,允许用户将一个生成器定义为上下文管理器,该装饰器将生成器中的代码通过yield语句分成两部分,yield之前的代码为__enter__方法,yield之后的代码为__exit__方法,yield的返回值即__enter__方法的返回值,用于赋给as后的变量。

实现资源管理

import contextlib

@contextlib.contextmanager
def open_func(file_name):
# __enter__方法
print('open file:', file_name, 'in __enter__')
file_handler = open(file_name, 'r') # 【重点】:yield
yield file_handler # __exit__方法
print('close file:', file_name, 'in __exit__')
file_handler.close()
return with open_func('userinfo.txt') as file_in:
for line in file_in:
print(line)

实现异常捕获

import contextlib
import traceback
import sys
@contextlib.contextmanager
def open_func(file_name):
# __enter__方法
print('open file:', file_name, 'in __enter__')
file_handler = open(file_name, 'r') try:
yield file_handler
except Exception as exc:
exc_type, exc_val, exc_tb = sys.exc_info()
print("异常类型:", exc_type)
print("异常值:", exc_val)
traceback.print_tb(exc_tb, -1)
print('the exception was thrown')
finally:
print('close file:', file_name, 'in __exit__')
file_handler.close() return with open_func('userinfo.txt') as file_in:
for line in file_in:
print(1/0)
print(line)

上下文管理器及with的相关总结的更多相关文章

  1. python上下文管理器ContextLib及with语句

    http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...

  2. 上下文管理器——with语句的实现

    前言 with语句的使用给我们带来了很多的便利,最常用的可能就是关闭一个文件,释放一把锁. 既然with语句这么好用,那我也想让我自己写的代码也能够使用with语句,该怎么实现? 下面具体介绍怎样实现 ...

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

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

  4. python 黑魔法 ---上下文管理器(contextor)

    所谓上下文 计算机上下文(Context)对于我而言,一直是一个很抽象的名词.就像形而上一样,经常听见有人说,但是无法和现实认知世界相结合. 最直观的上下文,莫过于小学的语文课,经常会问联系上下文,推 ...

  5. Python上下文管理器(Context managers)

    上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还 ...

  6. python中的with的用法,上下文管理器

    with是从Python2.5引入的一个新的语法,它是一种上下文管理协议,目的在于从流程图中把 try,except 和finally 关键字和 资源分配释放相关代码统统去掉,简化try….excep ...

  7. Python 上下文管理器模块--contextlib

    在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...

  8. Python核心技术与实战——二一|巧用上下文管理器和with语句精简代码

    我们在Python中对于with的语句应该是不陌生的,特别是在文件的输入输出操作中,那在具体的使用过程中,是有什么引伸的含义呢?与之密切相关的上下文管理器(context manager)又是什么呢? ...

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

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

随机推荐

  1. 图解Mongo Shell的使用

    mongo shell是一个MongoDB的交互式JavaScript接口.您可以使用mongo shell来查询和更新数据以及执行管理操作. 本篇经验将和大家介绍Mongo Shell的使用方法,希 ...

  2. Spring Boot (十): Spring Boot Admin 监控 Spring Boot 应用

    Spring Boot (十): Spring Boot Admin 监控 Spring Boot 应用 1. 引言 在上一篇文章<Spring Boot (九): 微服务应用监控 Spring ...

  3. Centos6 日常使用小结

    网络配置目录 1./etc/sysconfig/network-script/ifcfg-eth0 2.netstat -rn Kernel IP routing table Destination ...

  4. MongoDB 学习笔记之 DBRef

    DBRef: MongoDB建模有两种方式,一种是内嵌(Embed),另一种是连接(Link).内嵌比较好理解,就是字段内容是个数组,数组内再包含文档,而我们今天介绍的是另一种,称为链接DBRef.由 ...

  5. 三个Eclipse下的Debug的使用场景(五)

    本文链接:https://blog.csdn.net/u011781521/article/details/55000066    http://blog.csdn.net/u010075335/ar ...

  6. golang面试题--string操作

    题目: 请实现一个算法,确定一个字符串的所有字符[是否全都不同].这里我们要求[不允许使用额外的存储结构].给定一个string,请返回一个bool值,true代表所有字符全都不同,false代表存在 ...

  7. 我在用的翻译软件 -> 微软翻译+网易有道词典+谷歌翻译

    Windows网页翻译 因为微软翻译相对来说翻译网页更为准确,我也喜欢用谷歌的Chrome浏览器,但是我没找到微软翻译的扩展,这里只能放弃 这个需要配合Microsoft Edge浏览器进行使用,也是 ...

  8. python编程基础之十一

    循环语句:周而复始,在满足某个条件下,重复做相同或类型的事情, 循环语句三要素:循环条件 + 循环体 + 循环条件改变while 条件 : 循环体 循环条件改变... while 条件 : 循环体 循 ...

  9. Bribe the Prisoners SPOJ - GCJ1C09C

    Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. ...

  10. Java中Integer与int对比的一些坑

    Integer与int类型的关系 Integer是int的包装类,int的默认值是0,而Integer的默认值是null(我们经常在代码中使用的Integer.valueOf() 和xx.intVal ...