【Python】上下文管理协议__enter__和__exit__函数

部分程序中,可能事先要准备资源,事后做清理工作。 with方法就是python的非常酷的语句,安全可靠,方便。我们自己的类如何具备with的能力?必须拥有__enter__()函数和一个__exit__()函数,本章节介绍两个函数的能力。

        对于这种场景,一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

一、with语句

1,文件读取操作,通常打开一个文件,然后读取文件内容,最后需要关闭文件,代码如下:

f = open("./demofile2",mode="r",encoding="UTF-8")
for content in f:print(content)
f.close()

这样的程序文件打开正常时没问题,但是存在2个问题

  •  可能忘记关闭文件句柄;
  •  文件读取数据发生异常,没有进行任何处理。

 

2,使用with语句如下:

with open("./demofile2",mode="r",encoding="UTF-8") as f:data = f.read()# 离开with语句文件自动关闭
print(data)

3,with语句执行过程
        with操作很魔法,Python对with的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。

        执行过程概述,with后面的语句被执行后,__enter__()函数被调用,_enter__()的返回值将被赋值给as后面的变量,后边详细说明_enter__()函数返回值问题。当with后面的代码块全部被执行完之后,将调用_enter__()返回对象的__exit__()方法。

函数及参数说明:

  • __enter__(self):当with开始运行的时候触发此方法的运行
  • __exit__(self, exc_type, exc_val, exc_tb):当with运行结束之后触发此方法的运行
  • exc_type如果抛出异常,这里获取异常的类型
  • exc_val如果抛出异常,这里显示异常内容
  • exc_tb如果抛出异常,这里显示所在位置

4,代码示例

class ConvertType(object):def __enter__(self):print("Entry with!")def __exit__(self,type,value,trace):print(f"type:{type}")print(f"value:{value}")print(f"trace:{trace}")print("Exit with!")def strToInt(self,targetString:str) -> int:return int(targetString)with  ConvertType() as f:print(f)f.strToInt("1343f")print("Done!")

4.1 执行结果

首先预测一下代码能否正常执行,尝试执行结果如下:

Entry with!
None
type:<class 'AttributeError'>
value:'NoneType' object has no attribute 'strToInt'
trace:<traceback object at 0x1110a6b80>
Exit with!
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[30], line 2119 with  ConvertType() as f:20     print(f)
---> 21     f.strToInt("1343f")23 print("Done!")AttributeError: 'NoneType' object has no attribute 'strToInt'

报错分析:

发现print(f)打印为:None ,自然无法调用strToInt函数,也就是没有进入with...as代码块,原因如下:

with 语句执行时调用__enter__函数返回的对象成为f,这里__enter__函数没有return语句,默认返回None,因此f就是None

因此需要__enter__函数返回实例对象,修改代码如下:

class ConvertType(object):def __enter__(self):print("Entry with!")return self #新增一行返回值对象本身selfdef __exit__(self,type,value,trace):print(f"type:{type}")print(f"value:{value}")print(f"trace:{trace}")print("Exit with!")def strToInt(self,targetString:str) -> int:return int(targetString)with  ConvertType() as f:print(f)f.strToInt("1343f")print("Done!")

4.2 __enter__函数加返回值执行结果

Entry with!
<__main__.ConvertType object at 0x110fca000>
type:<class 'ValueError'>
value:invalid literal for int() with base 10: '1343f'
trace:<traceback object at 0x111070500>
Exit with!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[31], line 2119 with  ConvertType() as f:20     print(f)
---> 21     f.strToInt("1343f")23 print("Done!")Cell In[31], line 16, in ConvertType.strToInt(self, targetString)15 def strToInt(self,targetString:str) -> int:
---> 16     return int(targetString)ValueError: invalid literal for int() with base 10: '1343f'

报错分析:

发现程序已经执行到了with...as代码块,在执行f.strToInt函数时报错了,原因是传入的参数“1343f”无法转化为int类型。另外我们还发现在with...as代码块执行失败后,最后一行代码print("Done!")没有被执行。

原因是__exit__函数没有返回值,在没有返回值的情况下,with...as代码块执行失败后,代码块程序会中断,即剩余代码块程序不会被执行,直接执行__exit__函数,__exit__函数无返回值的情况下会将错误暴露出来,如上执行结果。

那么给__exit__函数增加返回值“True”,修改代码:

class ConvertType(object):def __enter__(self):print("Entry with!")return selfdef __exit__(self,type,value,trace):print(f"type:{type}")print(f"value:{value}")print(f"trace:{trace}")print("Exit with!")return True #新增一行返回值Truedef strToInt(self,targetString:str) -> int:return int(targetString)with  ConvertType() as f:print(f)f.strToInt("1343f")print("Done!")

4.3 __exit__函数加返回值后执行结果

Entry with!
<__main__.ConvertType object at 0x1102c9c40>
type:<class 'ValueError'>
value:invalid literal for int() with base 10: '1343f'
trace:<traceback object at 0x1105d2180>
Exit with!
Done!

执行结果分析:

同样是参数“1343f”执行strToInt函数报错,但是错误信息被“吞掉”,没有暴露出来,而with...as语句块之外的剩余语句被执行,输出Done!

说明在__exit__函数返回True时,执行with...as代码块发生异常时会包装异常,执行会中断当前with...as语句块,然后执行执行__exit__函数,最后with语句以外的代码。

4.4 正常执行测试

给定一个数字类型的字符串进行测试,如“1343”,执行结果如下:

Entry with!
<__main__.ConvertType object at 0x1102ca450>
type:None
value:None
trace:None
Exit with!
Done!

说明在with...as语句块正常执行时,传入__exit__函数的参数type,value,trace都为None。

5,总结

发现python语言with语句有很大的魔力,类似我们编写try...except...finally结构的程序,但是with语句很优雅、便捷。在处理文件打开关闭、网络链接打开关闭、事务性程序的事务打开和关闭等都可以在__exit__函数中释放资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序使用 Vant Weapp 中 Collapse 折叠面板 的问题!

需求&#xff1a;结合Tab 标签页 和 Collapse 折叠面板 组合成显示课本和章节内容&#xff0c;并且用户体验要好点&#xff01; 如下图展示&#xff1a; 问题&#xff1a;如何使用Collapse 折叠面板 将内容循环展示出来&#xff1f; js中的数据是这样的 代码实现&#xff1…

draw.io: 开启图表绘制的无限可能

图表是沟通和呈现复杂信息的有效工具&#xff0c;在工作、学习甚至生活中都有广泛的应用。作为一款在线图表软件&#xff0c;draw.io提供了简单、直观又功能丰富的界面&#xff0c;让任何人都可以轻松创建专业水准的图表。接下来&#xff0c;我将分享我深入使用draw.io的经验&a…

【C语言】归并排序算法实现

一、归并排序原理二、归并排序实现三、归并排序优化四、总结 归并排序&#xff08;Merge Sort&#xff09;是一种经典的排序算法&#xff0c;由于其采用了分治策略&#xff0c;因此在处理大数据集时表现出了较好的性能。本文将详细介绍归并排序的原理、实现以及优化方法&#x…

Python | Leetcode Python题解之第39题组合总和

题目&#xff1a; 题解&#xff1a; from typing import Listclass Solution:def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:def dfs(candidates, begin, size, path, res, target):if target < 0:returnif target 0:res.append(p…

Stability AI 发布 SD3 API:开启人工智能新篇章

文章目录 1.Stable Diffusion 3 API开放了! 2.Stability AI Document地址3.获取API Key4.API方式调用SD3出图接口地址接口请求规范接口请求响应结果 5.Stable Diffusion 3.0、Stable Image Core、Fooocus 2.3.1、MidJounery效果查看 1.Stable Diffusion 3 API开放了! Stabilit…

竞态问题 + axios 取消请求

目录 1&#xff0c;问题描述2&#xff0c;解决1&#xff0c;丢弃错误的结果2&#xff0c;取消之前的请求在页面中使用 3&#xff0c;其他4&#xff0c;潜在的问题 1&#xff0c;问题描述 在日常开发中&#xff0c;可能会有以下场景&#xff1a; 有多个 tab 页&#xff0c;每个…

react 响应式栅格布局

遇到一个小问题 , 有很多的下拉框放在了一行的盒子里 用到了栅格思路 , 但响应式处理屏幕时候右侧的按钮会覆盖掉样式 之前我的思路是子绝父相 , 将按钮定在最右侧 , 按钮和下拉框都在同一盒子中 , 且做了栅格处理没想到还是会覆盖解决 : 后来我用到了 margin-left: auto 来让…

蓝桥杯 BASIC-25 基础练习 回形取数

蓝桥杯 BASIC-25 基础练习 回形取数 问题描述 回形取数就是沿矩阵的边取数&#xff0c;若当前方向上无数可取或已经取过&#xff0c; 则左转90度。一开始位于矩阵左上角&#xff0c;方向向下。 输入格式 输入第一行是两个不超过200的正整数m, n&#xff0c;表示矩阵的行和列。 …

RedisHttpSession反序列化UID问题跟踪

1.RedisHttpSession配置 package com.visy.configure;import org.springframework.context.annotation.Configuration; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;Configuration EnableRedisHttpSession(maxInactive…

安卓手机APP开发__媒体开发部分__直播流

安卓手机APP开发__媒体开发部分__直播流 目录 概述 检查和监控直播的播放 在直播流中的定位查找 直播播放的用户界面 配置直播播放的参数 播放速度调整 定制播放速度的调整算法 直播窗口背后的异常和ERROR_CODE_BEHIND_LIVE_WINDOW 概述 ExoPlayer没有任何特殊配置的…

蓝桥杯2024年第十五届省赛真题-宝石组合

思路&#xff1a;参考博客&#xff0c;对Ha,Hb,Hc分别进行质因数分解会发现&#xff0c;S其实就等于Ha&#xff0c;Hb&#xff0c;Hc的最大公约数&#xff0c;不严谨推导过程如下&#xff08;字丑勿喷&#xff09;&#xff1a; 找到此规律后&#xff0c;也不能枚举Ha&#xff…

OpenCV——Niblack局部阈值二值化方法

目录 一、Niblack算法1、算法概述2、参考文献二、代码实现三、结果展示OpenCV——Niblack局部阈值二值化方法由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、Niblack算法 1、算法概述 Niblack 算法是一种典型的局部阈值…

JavaWeb开发05-事务管理-AOP概述-AOP通知类型-通知顺序-切入点表达式-连接点-案例

一、事务管理 1.事务回顾 2.Spring事务管理 删除部门和删除部门下的员工应该绑定在一起&#xff0c;但是如果这两个操作之间出现错误&#xff0c;就会执行删除部门不删除员工&#xff0c;所以需要使用事务将两个任务绑定在一起&#xff0c;要么一起成功要么一起失败 Spring中如…

如何通过自动化采购管理软件解决 6 个采购挑战?

采购需要精确性、可预测性以及敏捷而自信地解决问题的能力。灵活采购流程可以帮助企业更快地适应市场变化和供应链中断。 借助正确的工具&#xff0c;团队可以实现这些目标。 采用流程自动化技术的主要好处 当被问及采用流程自动化工具带来的好处时&#xff0c;三分之二的高…

基础知识集合

https://blog.csdn.net/sheng_q/category_10901984.html?spm1001.2014.3001.5482 epoll 事件驱动的I/O模型&#xff0c;同时处理大量的文件描述符 内核与用户空间共享一个事件表&#xff1a;监控的文件描述符以它们的状态&#xff0c;当状态变化&#xff0c;内核将事件通知给…

2024年二级造价师(建设工程造价管理)考试题库及答案

一、选择题 6.关于工程量清单方式招标的工程合同价格风险及风险分担&#xff0c;下列说法中正确的是&#xff08;  &#xff09;。 A.人工费变化发生的风险全部由发包人承担 B.承包人管理费的风险一般由发承包双方共同承担 C.当出现的风险内容及幅度在招标文件规定的范围…

Docker(十):Redis三主三从(扩容、缩容)

一&#xff1a;启动6台Redis # privilegedtrue 获取宿主机root权限 # --cluster-enabled yes 开启redis集群 # --appendonly yes 开启持久化 docker run -d --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/dataredis:6.0.8--cluster-en…

Mac上Maven的安装和环境变量配置保姆级教程(最新版实时更新)

目录 一、Maven的安装 1.进入官网&#xff08;Maven官网&#xff09;下载安装包并解压 2.这里我使用了Homebrew安装Maven 安装Homebrew&#xff1a; 安装Maven&#xff1a; 二、Maven配置环境变量 1.打开环境变量文档&#xff1a; 2.在弹出文档结尾加入配置&#xff1a…

SpringBoot常用20个注解及其作用

1、SpringBootApplication: 这是一个组合注解&#xff0c;包括了Configuration、EnableAutoConfiguration 和 ComponentScan。它标识了一个主程序类&#xff0c;用于启动 Spring Boot 应用。 2、RestController: 这个注解用于标识一个类&#xff0c;表示这个类中的所有方…

【Node.js】 fs模块全解析

&#x1f525;【Node.js】 fs模块全解析 &#x1f4e2; 引言 在Node.js开发中&#xff0c;fs模块犹如一把万能钥匙&#xff0c;解锁着整个文件系统的操作。从读取文件、写入文件、检查状态到目录管理&#xff0c;无所不能。接下来&#xff0c;我们将逐一揭开fs模块中最常用的那…