上下文管理器——with语句的实现
前言
with语句的使用给我们带来了很多的便利,最常用的可能就是关闭一个文件,释放一把锁。
既然with语句这么好用,那我也想让我自己写的代码也能够使用with语句,该怎么实现?
下面具体介绍怎样实现一个自己的with语句
使用类实现
要想使用with语句,那就要遵循with语句的使用规矩,也就是上下文管理器协议
这个协议提示我们要在类中去实现两个特殊方法,enter(self)和exit(self, exc_type, exc_val, exc_tb)
有了这两个方法,就可以使用with语句执行了,它的执行过程为先执行enter(self)方法,然后执行你添加在with下的代码,然后最后执行exit方法
如果在执行的过程中出现了异常,那么会自动执行exit方法,
class ErrorProduce:
def __init__(self):
pass
def produce(self):
raise RuntimeError('ERROR')
class MyWith:
def __enter__(self):
return ErrorProduce()
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print("有错")
#print(exc_val)
#return True
else:
print("完美执行")
with MyWith() as E:
E.produce()
将上述代码运行,会先打印出“有错”,然后再打印出相关错误,然后程序由于错误终止,也就是说,在产生了错误后,还是执行了exit中的代码
如果将exit中的两个注释符号去掉的话,那么再次运行程序不会报错,但会将exc_val中的错误信息打印出来,这里相当于通过exit方法将错误抹除掉了,抹除方式为返回True,但也把with中抛出错误后的所有代码都跳过了。
使用函数实现
通过引入contextlib模块中的contextmanager装饰器,装饰函数使函数可以使用with语句
from contextlib import contextmanager
class ErrorProduce:
def __init__(self):
pass
def produce(self):
raise RuntimeError('ERROR')
@contextmanager
def my_with():
try:
yield ErrorProduce()
except Exception as e:
print(e)
#raise
finally:
print('收尾')
with my_with() as E:
E.produce()
print('aa')
函数中使用了yield,那么它也就变成了生成器,通过yield来划分相当于类中的enter和exit,yield返回的值也就是可以用作as后的值
上段代码中我们发现使用了try,except,finally异常处理的语句,这些语句是必要的吗?
通过测试,如果没有这些异常处理,那么with语句还是可以执行的,这里的意思是可以使用with语句,不会报不能使用with的错误,但是使用后,只有with下的语句中没有抛出异常,那么yield语句后边的代码才会执行,一旦有异常抛出,仍然是程序运行终止。所以,一般还是要配合try,except,finally语句来构造。
还有一点要注意,使用这种方式,异常被except捕捉后,那么这个异常就失效了,一般的我们还是会需要在except中再次将捕捉的异常抛出,也就是在后面加上raise,因为我们使用with只是为了做好一个收尾,如关闭文件句柄。或者另一种方式,我们干脆就不写except语句,直接写finally语句了。
- 文章中出现的棕色加粗的单词,是由于markdown-here将特殊方法两边的下划线转换产生的,原意为特殊方法
上下文管理器——with语句的实现的更多相关文章
- python2.7高级编程 笔记一(Python中的with语句与上下文管理器学习总结)
0.关于上下文管理器上下文管理器是可以在with语句中使用,拥有__enter__和__exit__方法的对象. with manager as var: do_something(var) 相当于以 ...
- with/as上下文管理器
# -*- coding: utf-8 -*- #python 27 #xiaodeng #Python学习手册 868 #with/as上下文管理器 #with语句的基本格式: with open( ...
- Python中的上下文管理器(contextlib模块)
上下文管理器的任务是:代码块执行前准备,代码块执行后收拾 1 如何使用上下文管理器: 打开一个文件,并写入"hello world" filename="my.txt&q ...
- 【Python学习笔记】with语句与上下文管理器
with语句 上下文管理器 contextlib模块 参考引用 with语句 with语句时在Python2.6中出现的新语句.在Python2.6以前,要正确的处理涉及到异常的资源管理时,需要使用t ...
- python上下文管理器及with语句
with语句支持在一个叫上下文管理器的对象的控制下执行一系列语句,语法大概如下: with context as var: statements 其中的context必须是个上下文管理器,它实现了两个 ...
- Python中的上下文管理器和with语句
Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先, ...
- python上下文管理器ContextLib及with语句
http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...
- python之with语句结合上下文管理器
所谓上下文管理器即在一个类中重写了__enter__方法和__exit__方法的类就可以成为上下文管理器类. 我们可以通过with语句结合上下文管理器简化一些操作. 使用with语句结合自定义上下文管 ...
- Python核心技术与实战——二一|巧用上下文管理器和with语句精简代码
我们在Python中对于with的语句应该是不陌生的,特别是在文件的输入输出操作中,那在具体的使用过程中,是有什么引伸的含义呢?与之密切相关的上下文管理器(context manager)又是什么呢? ...
随机推荐
- Eureka编程
在一些场景下,我们需要监听eureka服务中心的一些状态,譬如某个微服务挂掉了,我们希望能监听到,并给管理员发送邮件通知或钉钉告警. 一.Eureka的监听事件,可以用来监控.告警EurekaInst ...
- Linux压力测试软件Stress安装及使用
一.安装 yum install -y epel-release yum install stress -y 二.参数说明 -? --help 显示帮助信息 --version 显示软件版本信息 -t ...
- Go 语言实践(一)
本文由Austin发表 指导原则 我们要谈论在一个编程语言中的最佳实践,那么我们首先应该明确什么是"最佳".如果您们听了我昨天那场讲演的话,您一定看到了来自 Go 团队的 Russ ...
- 【PyTorch深度学习60分钟快速入门 】Part3:神经网络
神经网络可以通过使用torch.nn包来构建. 既然你已经了解了autograd,而nn依赖于autograd来定义模型并对其求微分.一个nn.Module包含多个网络层,以及一个返回输出的方法f ...
- java基础之继承(一)
虽然说java中的面向对象的概念不多,但是具体的细节还是值得大家学习研究,java中的继承实际上就是子类拥有父类所有的内容(除私有信息外),并对其进行扩展.下面是我的笔记,主要包含以下一些内容点: 构 ...
- U3D MonoBehaviour
一.简介 MonoBehaviour是每个脚本派生类的基类,它定义了一个脚本文件从最初被加载到最终被销毁的一个完整过程. 这个过程通过对应的方法体现出来,在不同的方法完成不同的功能,我们把这些方法称为 ...
- Java的XML解析
XML:(eXtensible Markup Language) 可扩展标记语言 是一种数据格式,用于存储和传输数据 声明一个xml文件 <?xml version="1.0" ...
- jquery只能输入数字
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- mui 实用封装销毁页面
/* * 描述:页面销毁封装 * 说明:针对订单特殊定位页面 * 返回首页,页面空白前进行销毁页面处理 * 使用:plusReady之后 */ (function(w) { var destructi ...
- 5.数码相框-额外项目电子书总结,并使用svgalib库
在LCD显示任意编码的文本文件,类似电子书 怎样在LCD上显示文件: 需要哪几个文件? 1.顶部文件 通过main.c分析命令行的操作,然后初始化各个管理文件下的结构体,比如DisplayInit() ...