什么是上下文管理器

基本语法

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. Spring Boot 整合视图层技术

    这一节我们主要学习如何整合视图层技术: Jsp Freemarker Thymeleaf 在之前的案例中,我们都是通过 @RestController 来处理请求,所以返回的内容为json对象.那么如 ...

  2. TensorFlow2.0(四):填充与复制

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  3. C++——数组与字符串

    目录 一.数组 1.1定义与初始化 1.1.1使用 1.1.2存储 1.1.3初始化 1.2作函数参数 1.3对象数组 1.3.1定义与访问 1.3.2初始化 1.3.3数组元素所属类的构造函数 二. ...

  4. 快学Scala 第九课 (伴生对象和枚举)

    Scala没有静态方法和静态字段, 你可以用object这个语法结构来达到同样的目的. 对象的构造器只有在第一次被使用时才调用. 伴生对象apply方法: 类和它的伴生对象可以互相访问私有特性,他们必 ...

  5. python编程基础之三十

    时间模块: 时间戳:就是当前是键距离1970年1月1日0:0:0的秒数,后面还带小数,可以说是非常精确 时间的表示形式: a.以整数或者浮点数表示一个以秒为单位的时间间隔,这个时间的基础值1970.1 ...

  6. 由一次线上故障来理解下 TCP 三握、四挥 & Java 堆栈分析到源码的探秘

    本文导读: 生产故障场景介绍 TCP 建连三次握手过程 TCP 断连四次挥手过程 结合 Java 堆栈剖析源码 再从堆栈中找到"罪魁祸首" 问题优化方案总结 1.生产故障场景介绍 ...

  7. Spring Cloud Alibaba学习笔记(3) - Ribbon

    1.手写一个客户端负载均衡器 在了解什么是Ribbon之前,首先通过代码的方式手写一个负载均衡器 RestTemplate restTemplate = new RestTemplate(); // ...

  8. DJango错误日志生成

    DJango错误日志生成 setting.py设置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': ...

  9. java-try,return和finally相遇时的各种情况

    今天碰到了这样一个问题:使用try,return和finally会碰到的各种情况1,try中有return时,执行顺序:2,try和finally中都有return时,执行顺序:3,运算代码在fina ...

  10. 4. NFS存储服务器搭建

    1.什么是NFS? Network file system 网络文件系统 nfs共享存储 2.nfs能干什么? nfs 能为 不同主机系统之间 实现 文件的共享 3.为什么要使用nfs? 在集群架构中 ...