什么是上下文管理器

基本语法

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. jobs后台任务

    前台作业:占据了命令提示符,就是你当前可以操作的作业后台作业:启动之后,释放命令提示符,后续的操作在后台完成 前台——>后台 ctrl+z:把正在前台的作业送往后台,这时作业的状态是暂停. CO ...

  2. SpringBoot导入jsp依赖始终报错

    先粘出我自己的pom代码: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...

  3. vue自定义指令,比onerror更优雅的方式实现当图片加载失败时使用默认图,提供三种方法

    首先,来看下效果图(演示一下图片正常加载与加载失败时的效果) 在线体验地址:https://hxkj.vip/demo/vueImgOnerror/ 一.常规方法解决 我们都知道,img标签支持one ...

  4. 智慧金融时代,大数据和AI如何为业务赋能

    前言:宜信技术人物专访是宜信技术学院推出的系列性专题,我们邀请软件研发行业的优秀技术人,分享自己在软件研发领域的实践经验和前瞻性观点. 第一期专访我们邀请到宜信科技中心AI中台负责人王东老师,从大数据 ...

  5. Linux 命令个人笔记

    [表示命令]man -f [] 显示一个命令的功能whatis [] 显示一个命令的功能ls -lR | grep '^-' | wc -l 统计一个目录下总共有多少个文件head [-n numbe ...

  6. Vue-懒加载(判断元素是否在可视区域内)

    上公式: 元素距离顶部高度(elOffsetTop) >= dom滚动高度(docScrollTop) 并且元素距离顶部高度(elOffsetTop) < (dom滚动高度 + 视窗高度) ...

  7. day 20作业

    目录 1.下面这段代码的输出结果将是什么?请解释. 2.多重继承的执行顺序,请解答以下输出结果是什么?并解释. 3.什么是新式类,什么是经典类,二者有什么区别?什么是深度优先,什么是广度优先? 4.用 ...

  8. 配置mysql可局域网内访问

    一 进入mysql输入密码 :mysql -u root -p二 执行可局域网访问命令:GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY ...

  9. app微信支付

    <?php namespace app\api\controller\v1; use think\Request; use app\api\exception\weappay\lib\WxPay ...

  10. 《java编程思想》P160-P180(第八章部分+第九章部分)

    1.什么是多态? 多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行为方式.(发送消息就是函数调用) 现实中,关于多态的例子不胜枚举.比方说按下 F1 ...