Python 异步: 异步上下文管理器(17)

2023-11-18

动动发财的小手,点个赞吧!

上下文管理器是一种 Python 构造,它提供了一个类似 try-finally 的环境,具有一致的接口和方便的语法,例如通过“with”表达。

它通常与资源一起使用,确保在我们完成资源后始终关闭或释放资源,无论资源的使用是成功还是因异常而失败。

Asyncio 允许我们开发异步上下文管理器。

我们可以通过定义一个将 aenter() 和 aexit() 方法实现为协程的对象来在 asyncio 程序中创建和使用异步上下文管理器。

1. 什么是异步上下文管理器

异步上下文管理器是一个实现了 aenter() 和 aexit() 方法的 Python 对象。

在我们深入了解异步上下文管理器的细节之前,让我们回顾一下经典的上下文管理器。

1.1. Context Manager

上下文管理器是一个 Python 对象,它实现了 enter() 和 exit() 方法。

  • enter() 方法定义了块开头发生的事情,例如打开或准备资源,如文件、套接字或线程池。
  • exit() 方法定义退出块时发生的情况,例如关闭准备好的资源。

通过“with”表达式使用上下文管理器。通常,上下文管理器对象是在“with”表达式的开头创建的,并且会自动调用 enter() 方法。内容的主体通过命名的上下文管理器对象使用资源,然后 aexit() 方法在块退出时自动调用,通常或通过异常。

...
# open a context manager
with ContextManager() as manager:
 # ...
# closed automatically

这反映了 try-finally 表达式。

...
# create the object
manager = ContextManager()
try:
 manager.__enter__()
 # ...
finally:
 manager.__exit__()

1.2. Asynchronous Context Manager

“PEP 492 – Coroutines with async and await syntax”引入了异步上下文管理器。

它们提供了一个上下文管理器,可以在进入和退出时挂起。

aenteraexit 方法被定义为协同程序,由调用者等待。这是使用“async with”表达式实现的。

因此,异步上下文管理器只能在 asyncio 程序中使用,例如在调用协程中。

  • 什么是“async with”

“async with”表达式用于创建和使用异步上下文管理器。它是“with”表达式的扩展,用于异步程序中的协程。

“async with”表达式就像用于上下文管理器的“with”表达式,除了它允许在协同程序中使用异步上下文管理器。

为了更好地理解“async with”,让我们仔细看看异步上下文管理器。async with 表达式允许协程创建和使用上下文管理器的异步版本。

...
# create and use an asynchronous context manager
async with AsyncContextManager() as manager:
 # ...

这相当于:

...
# create or enter the async context manager
manager = await AsyncContextManager()
try:
 # ...
finally:
 # close or exit the context manager
 await manager.close()

请注意,我们正在实现与传统上下文管理器大致相同的模式,只是创建和关闭上下文管理器涉及等待协程。

这会暂停当前协程的执行,调度一个新的协程并等待它完成。因此,异步上下文管理器必须实现必须通过 async def 表达式定义的 aenter() 和 aexit() 方法。这使得它们自己协程也可能等待。

2. 如何使用异步上下文管理器

在本节中,我们将探讨如何在我们的 asyncio 程序中定义、创建和使用异步上下文管理器。

2.1. 定义

我们可以将异步上下文管理器定义为实现 aenter() 和 aexit() 方法的 Python 对象。

重要的是,这两种方法都必须使用“async def”定义为协程,因此必须返回可等待对象。

# define an asynchronous context manager
class AsyncContextManager:
    # enter the async context manager
    async def __aenter__(self):
        # report a message
        print('>entering the context manager')
 
    # exit the async context manager
    async def __aexit__(self, exc_type, exc, tb):
        # report a message
        print('>exiting the context manager')

因为每个方法都是协程,所以它们本身可能等待协程或任务。

# define an asynchronous context manager
class AsyncContextManager:
    # enter the async context manager
    async def __aenter__(self):
        # report a message
        print('>entering the context manager')
        # block for a moment
        await asyncio.sleep(0.5)
 
    # exit the async context manager
    async def __aexit__(self, exc_type, exc, tb):
        # report a message
        print('>exiting the context manager')
        # block for a moment
        await asyncio.sleep(0.5)

2.2. 使用

通过“async with”表达式使用异步上下文管理器。这将自动等待进入和退出协程,根据需要暂停调用协程。

...
# use an asynchronous context manager
async with AsyncContextManager() as manager:
 # ...

因此,“async with”表达式和异步上下文管理器更普遍地只能在 asyncio 程序中使用,例如在协程中。

现在我们知道如何使用异步上下文管理器,让我们看一个有效的例子。

3. 异步上下文管理器和“异步”示例

我们可以探索如何通过“async with”表达式使用异步上下文管理器。

在这个例子中,我们将更新上面的例子,以正常方式使用上下文管理器。

我们将使用“async with”表达式,并在一行中创建并进入上下文管理器。这将自动等待 enter 方法。

然后我们可以在内部块中使用管理器。在这种情况下,我们将只报告一条消息。

退出内部块将自动等待上下文管理器的退出方法。将这个例子与前面的例子进行对比,可以看出“async with”表达式在 asyncio 程序中为我们做了多少繁重的工作。

# SuperFastPython.com
# example of an asynchronous context manager via async with
import asyncio
 
# define an asynchronous context manager
class AsyncContextManager:
    # enter the async context manager
    async def __aenter__(self):
        # report a message
        print('>entering the context manager')
        # block for a moment
        await asyncio.sleep(0.5)
 
    # exit the async context manager
    async def __aexit__(self, exc_type, exc, tb):
        # report a message
        print('>exiting the context manager')
        # block for a moment
        await asyncio.sleep(0.5)
 
# define a simple coroutine
async def custom_coroutine():
    # create and use the asynchronous context manager
    async with AsyncContextManager() as manager:
        # report the result
        print(f'within the manager')
 
# start the asyncio program
asyncio.run(custom_coroutine())

运行示例首先创建 main() 协程并将其用作 asyncio 程序的入口点。

main() 协程运行并在“async with”表达式中创建我们的 AsyncContextManager 类的实例。

该表达式自动调用 enter 方法并等待协程。报告一条消息,协程暂时阻塞。

main() 协程恢复并执行上下文管理器的主体,打印一条消息。

块退出,自动等待上下文管理器的退出方法,报告消息并休眠片刻。

这突出了 asyncio 程序中异步上下文管理器的正常使用模式。

>entering the context manager
within the manager
>exiting the context manager

本文由 mdnice 多平台发布

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 异步: 异步上下文管理器(17) 的相关文章

随机推荐

  • STL deque 源码——deque特点、实现框架、源码分段剖析、常用函数总结(上)

    一 deque的一些特点 支持随机访问 即支持 以及at 但是性能没有vector好 可以在内部进行插入和删除操作 但性能不及list deque 两端 都能够快速插入和删除元素 而vector只能在尾端进行 deque的元素存取和迭代器操
  • 查新报告怎么写?

    一 查新报告怎么写 二 查新报告怎么查 查新报告一般是在查新机构里查 这里给大家推荐一个权威的专业查新机构 掌桥科研 掌桥科研是一家中国的科技信息服务公司 总部位于北京市 公司的主营业务是为中国的科学研究机构 大学 企业等提供科研数据和技术
  • 个人银行管理系统6(C改Java)

    C语言版本 date h ifndef DATE H define DATE H class Date 日期类 private int year 年 int month 月 int day 日 int totalDays 该日期是从公元元年
  • vue项目中跳转到外部链接方法

    div 点我 div goPage url window location href url 直接跳转去外部的a链接
  • 关于Keil中Memory中观察不到数据变化的问题以及启动文件栈的初始化

    关于Keil中Memory中观察不到数据变化的问题 在KEIL中观察Memory数据变化 一定要记得只能在RAM地址或ROM之内观察 如下图所示 RAM的地址设置在地址为0x20000000开始的地方 大小为0x20000 因此只有在这个范
  • gorm+docker+mysql

    简介 ORM Object Relational Mapping 框架采用元数据来描述对象与关系映射的细节 元数据一般采用XML格式 并且存放在专门的对象一映射文件中 简单理解为一种框架的格式 gorm是Golang中一个非常出色的 旨在对
  • 38个MySQL数据库的小技巧

    1 如何快速掌握MySQL 培养兴趣 兴趣是最好的老师 不论学习什么知识 兴趣都可以极大地提高学习效率 当然学习MySQL 5 6也不例外 夯实基础 计算机领域的技术非常强调基础 刚开始学习可能还认识不到这一点 随着技术应用的深 入 只有有
  • java之MySQL数据库

    MySQL数据库 1 什么是数据库 答 数据库是以一定方式存储在一起 能予多个用户共享 具有尽可能小的冗余度 与应用程序彼此独立的数据集合 2 数据库的分类 具体含义 常见的数据库 答 关系型数据库和非关系型数据库 关系数据库 是建立在关系
  • springCloud - 第10篇 - 服务间调用追踪 (zipkin 的使用)

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到教程 一 在微服务系统中 不同应用服务可能会有各种不同的相互调用 springcloud 集成了 zipkin 来实现对于不同服务调用的追踪和统计
  • LIBSVM 使用

    预备 NTU TW Chih Chung Chang and Chih Jen Lin LIBSVM LIBSVM Data Classification Regression and Multi label 正文 a 编译libsvm u
  • 【机器学习】决策树 No.3

    1 决策树之信息论基础 决策树思想来源非常朴素 程序设计中的条件分支结构 if else 最早的决策树就是利用这类结构分割数据的一种分类学习方法 例 银行贷款例子 使用决策树划分是否贷款 此处特征为两个 房子 工作 香农 信息论创始人 19
  • 一文带你了解ES6迭代器(iterator)

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 一 迭代器 iterator 是什么 二 工作原理 总结 一 迭代器 iterator 是什么 迭代器 iterator 是一种接口 为各种不同的数据结构提供统一的
  • SkipList(跳表)

    跳表简介 跳表是基于有序链表实现的搜索结构 是一种动态的搜索结构 即支持动态插入和删除操作 且跳表查找和删除的平均时间复杂度是Olog n 因此跳表是一种时间复杂度相对较小的搜索结构 我们知道对一个数据集合的查找 最差的时间复杂度是O n
  • Switch / Xbox / PS / PSV / PSP 游戏指南

    1 Switch Xbox PS PSV PSP 对比分析 table 1 PSV2000 1000 比较分析 PSV2000 相对 PSV1000 具体变更点 薄了20 轻了15 屏幕改为液晶屏 PS键 开始键和选择键变成球形更方便按 内
  • 2,一个人体姿态识别的项目实现

    学习opencv的例子 1 认识 2 start 直接干货 例子1 例子2 例子3 例子4 例子5 固定阈值 自适应阈值 文档说明 参考链接 http codec wang opencv start 02 basic element ima
  • git仓库创建及上传

    如何创建一个git仓库并上传代码 1 在此之前我们需要安装git和注册gitee账号 1 打开git官网下载安装程序 然后按照指令进行安装即可 2 搜索gitee进行注册和绑定邮箱即可 上传代码时需要登录gitee账号 安装成功之后告诉本地
  • Android apk 反编译解析

    学习android开发 有必要对android的反编译有所了解 当然学习android反编译并不是为了破解别人的软件 完全是一种学习的方法 了解别人写程序的思想是一件很有趣的事情 工具下载地址 http code google com p
  • androidstudio开发!花三分钟看完这篇文章你就懂了!技术详细介绍

    阿里面试 自我介绍 首先要介绍自己的项目经验和个人的擅长点 因为面试官主要考察你的表达能力和语言精简能力 简历的编写其实这里可能需要注意几点 1 标题的直接按照姓名 几年工作经验 应聘岗位格式来填写 例如 黄铭 四年工作经验 Android
  • STP与RSTP区别

    STP 不能快速迁移 即使是在点对点链路或边缘端口 边缘端口指的是该端口直接与用户终端相连 而没有连接到其它设备或共享网段上 也必须等待2 倍的ForwardDelay 的时间延迟 端口才能迁移到转发状态 RSTP Rapid Spanni
  • Python 异步: 异步上下文管理器(17)

    动动发财的小手 点个赞吧 上下文管理器是一种 Python 构造 它提供了一个类似 try finally 的环境 具有一致的接口和方便的语法 例如通过 with 表达 它通常与资源一起使用 确保在我们完成资源后始终关闭或释放资源 无论资源