Python_上下文管理器

news2024/11/17 17:54:39

目录

上下文管理器类

多上下文管理器

contextmanager实现上下文管理器


上下文管理器(context manager)是 Python 编程中的重要概念,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是with...as...

为了确保一些系统资源得以正确释放,我们经常会用到 try ... excepte ... finally 语句。如:

try:
   f = open('somefile')
   for line in f:
       print(line)
except Exception as e:
   print(e)
finally:
    f.close()

上面的代码模式,从用复用代码的模式来讲,并不够好。于是 with 语句出现了,通过定义一个上下文管理器来封装这个代码块:

with open('filename', 'r') as f:
   for line in f:
          print(line)

显然,with 语句比 try 语句简洁了许多。

上下文管理器类

由于 with 语句利用了上下文管理器,在深入理解 with 语句之前,我们先看看上下文管理器。我们要定义一个上下文管理器其实很简单,只要一个类实现了__enter__(self)和__exit__(self, exc_type, exc_valye, traceback)我们就叫他上下文管理器

__enter__(self) 返回一个对象,可以是当前类的实例,也可以是其他对象。

class SomeThing:
   def __enter__(self):
       return self        # 返回类实例

class LineLength:
   def __init__(self, filepath):
       self.__file = open(self.__filepath)

   def __enter__(self):
       return self.__file        # 返回其他对象

执行过程

下面让我们看看 with 语句具体是如何执行的。

第一步:执行上下文表达式以获得上下文管理器对象。上下文表达式就是 with 和 as 之间的代码。

第二步:加载上下文管理器对象的 __exit__()方法备用。

第三步:执行上下文管理器对象的__enter__()方法。

第四步:将__enter__()方法返回值绑定到 as 后面的 变量中。

第五步:执行 with 内的代码块。

第六步:执行上下文管理器的__exit__()方法。

如果在代码块中发生了异常,异常被传入__exit__()中。如果没有,__exit__()的三个参数会传入 None, None, None。__exit__()需要明确地返回 True 或 False。并且不能在__exit__()中再次抛出被传入的异常,这是解释器的工作,解释器会根据返回值来确定是否继续向上层代码传递异常。当返回 True 时,异常不会被向上抛出,代码会从报异常的代码处跳出上下文管理继续执行代码,当返回 False 时会向上抛出,阻断代码执行。当没有异常发生传入__exit__()时,解释器会忽略返回值。

import time


class File(object):
    def __init__(self, filename, mode):
        print("上下文管理执行顺序:\n1、执行初始化方法")
        self.f = open(filename, mode)

    def __enter__(self):
        print("2、执行__enter__()方法")
        return self     # "__enter__()方法的返回值绑定到 as 后面的 变量中

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        :param exc_type:如果抛出异常,返回异常类型,否则返回None
        :param exc_val:如果抛出异常,返回异常内容,否则返回None
        :param exc_tb:如果抛出异常,返回异常位置,否则返回None
        :return:
        """
        print("4、执行__exit__()方法")
        if exc_type:
            print(exc_type, "\n", exc_val, "\n", exc_tb)

        # 若代码块报错则立即执行__exit__()方法中的代码;若代码块没报错,执行完代码块后执行__exit__()方法中的代码"
        self.f.close()
        time.sleep(1)
        # return True     # 当返回 True 时,异常不会被向上抛出,代码会从报异常的代码处跳出上下文管理继续执行代码,
        return False    # 当返回 False 时会在__exit__()方法执行完后向上抛出,阻断代码执行。

    def reads(self):
        return self.f.read()


with File("README.md", "rb") as f:
    print("3、执行代码块代码")
    # 代码块部分
    f.reads()
    # 代码块报错,报错后的代码不会被执行
    print("若代码块报错,“我”不被执行;将r改为rb,代码块不报错“我”就执行")
print("若代码块报错,__exit__()方法中返回 Ture “我”才执行;若代码块不报错,“我”也执行")

执行结果:

把"rb"改为"r"后执行结果:

 

多上下文管理器

实际上,我们可以同时处理多个上下文管理器:

with A() as a, B() as b:
   suite

所以我们大可不必写嵌套的 with 语句。

contextmanager实现上下文管理器

Python还提供了一个contextmanager的装饰器,更进一步简化了上下文管理器的实现方法。通过yield将函数分割成两部分,yield之前的部分相当于在__enter__方法中执行,yield之后的部分相当于在__exit__方法中执行,紧跟在yield之后的返回值给as之后的变量。

from contextlib import contextmanager


class File:
    def __init__(self, filename, mode):
        self.f = open(filename, mode)

    def reads(self):
        return self.f.read()

    def closed(self):
        self.f.close()


@contextmanager
def read_file():
    print(1)
    rf = File("README.md", "rb")
    yield rf
    print(3)
    rf.closed()


with read_file() as f:
    print(2)
    f.reads()

执行结果:

 把"rb"改为"r"后执行结果:

 注:当报错后,没有打印3,不清楚yield下面的代码是否执行。


-事必有法,然后有成- 最后祝大家早日达到测试的天花板!



 以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以评论区,留言【777】直接拿走就好了

 

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

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

相关文章

【Kubernetes资源篇】ConfigMap配置管理中心详解

文章目录 一、ConfigMap配置中心理论知识1、ConfigMap配置中心简介2、ConfigMap局限性 二、创建ConfigMap的四种方式1、第一种:通过命令行创建ConfigMap2、第二种:通过指定文件创建ConfigMap3、第三种:通过指定目录创建ConfigMap4、第四种&am…

C++线程池(1)理论基础及简单实现

写过CURD的程序员肯定都熟悉“数据库连接池”这个东西,数据库连接是个昂贵的东西,因为它的创建过程比较耗费资源。所以为了节约资源、提高数据库操作的性能,“数据库连接池”就应运而生了。 其实线程池跟数据库连接池类似,一个线…

《PyTorch深度学习实践》第七讲 处理多维特征的输入

b站刘二大人《PyTorch深度学习实践》课程第七讲处理多维特征的输入笔记与代码:https://www.bilibili.com/video/BV1Y7411d7Ys?p7&vd_sourceb17f113d28933824d753a0915d5e3a90 Diabetes Dataset 每一行是一个记录每一列是一个特征,每个样本有8个特征…

为什么我们家里的IP都是192.168开头的?

为什么我们家里的IP都是192.168开头的? 本文为掘金社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究! 是的,还是我小白,什么技术博主,老情感博主了。 来讲个故事。…

网络安全合规-数据安全分类分级

数据安全是指保护数据免受未经授权的访问、使用、泄露、破坏或篡改的措施。数据安全包括物理安全、网络安全、应用程序安全、数据备份和恢复等方面。 数据分级分类是指根据数据的重要性和敏感程度,将数据划分为不同的级别,并根据不同级别的数据制定不同…

enote笔记法之附录1——“语法词”(即“关联词”)(ver0.23)

enote笔记法之附录1——“语法词”(即“关联词”)(ver0.23) 最上面的是截屏的完整版,分割线下面的是纯文字版本: 作者姓名(本人的真实姓名):胡佳吉 居住地&#xff1…

前言-----

因要参加电赛,接触到STC89C52RC(A51)单片机 STC89C52RC引脚功能 1电源: ①VCC - 芯片电源,接5V; ②VSS - 接地端; 2.时钟: XTAL1、XTAL2 - 晶体振荡电路反相输入端和输出端。 3.控制线: 控制线共…

Java 17官方编程手册都针对哪些方面做了更新?

Java 17,官方编程手册, 《International Developer》杂志称为“全世界醉著名的编程书籍创作者之一”的Herbert Schildt倾情解读 《Java官方编程手册》从1996年首次出版以来,已经经历了数次改版,每次改版都反映 了Java不断演化的进…

分享解析,2+1链动模式为何能在市场上经久不衰

​小编介绍:10年专注商业模式设计及软件开发,擅长企业生态商业模式,商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地;扶持10余个电商平台做到营收过千万,数百个平台达到百万会员,欢迎咨询。 随…

服务网格:Istio 架构

什么是服务网格 服务网格(Service Mesh)这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互。随着规模和复杂性的增长,服务网格越来越难以理解和管理。 它的需求包括服务发现、负载均衡、故障恢复、指标收集和监控以及通常更加复杂的运维需求&am…

数据结构--双端队列

数据结构–双端队列 双端队列(Double-ended Queue,简称Deque)是一种具有队列和栈特性的数据结构,可以在队列的两端进行插入和删除操作。双端队列允许从前端和后端同时进行插入和删除操作,因此可以称为“两端都可以进出…

「STC8A8K64D4开发板」第2-6讲:串口通信

第2-6讲:串口通信 学习目的掌握USB转串口电路的原理和设计。学习STC8A8K64D4的串口通信,包括串口初始化、波特率计算、串口发送和接收。编写串口收发程序,尤其是串口接收的软件缓存处理。编写串口发送命令控制LED指示灯亮灭的程序。 硬件电路…

【电商API接口系列】店铺所有商品数据的采集

API接口允许不同应用程序之间共享数据,在系统之间传输、读取和更新数据。例如,一个电商网站可以通过API接口获取支付系统的支付状态。API接口允许开发人员使用他人开发的功能来扩展自己的应用程序。通过调用第三方API接口,开发人员无需重新实…

二进制部署Kubernetes

二进制部署Kubernetes v1.20 k8s集群master01:192.168.142.10 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群master02:192.168.142.20 k8s集群node01:192.168.142.30 kubelet kube-proxy docker k8s集群node…

基于Java汽车售票网站设计实现(源码+lw+部署文档+讲解等)

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

VUE_网页自定义右键菜单组件

可以在uni-app或vue脚手架项目使用 引入组件会接管页面右键事件&#xff0c;所有options为空数组时&#xff0c;在页面右键将没有反应 rightMenu.vue <template><view><view v-if"show" class"contextMenu" :style"lay_style"…

Kafka:Kafka资料整理

一、官网 二、博主文章 1、kafka是什么 • Worktile社区 三、源码解读

一文了解云计算

目录 &#x1f34e;云服务 &#x1f34e;云计算类型 &#x1f352;公有云 &#x1f352;私有云 &#x1f352;混合云 &#x1f34e;云计算服务模式 &#x1f352;IaaS基础设施即服务 &#x1f352;PaaS平台即服务 &#x1f352;SaaS软件即服务 &#x1f352;三者之间区别 &…

4.springboot原理篇

原理篇 spring与springboot区别 spring是承载容器 springboot做的主要工作&#xff1a; ①简化配置&#xff08;省去了spring中配置xml&#xff0c;引入application.yml文件&#xff09; ②为我们提供了 spring-boot-starter-web 依赖&#xff0c;这个依赖包含了Tomcat和sprin…

二进制搭建Kubernetes集群(二)——部署Worker Node 组件

四.部署node节点 4.1 所有node节点部署 docker引擎 #所有 node 节点部署docker引擎#安装依赖包yum install -y yum-utils device-mapper-persistent-data lvm2#设置阿里云镜像源yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker- ce.…