首页 > 编程语言 >Python 异步: 异步上下文管理器(17)

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

时间:2023-03-12 12:34:01浏览次数:74  
标签:异步 管理器 Python manager context async 上下文

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

上下文管理器是一种 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多平台发布

标签:异步,管理器,Python,manager,context,async,上下文
From: https://www.cnblogs.com/swindler/p/17207975.html

相关文章

  • 一入python深似海,从此妹纸是路人(二)
    一、列表1.列表的切片[开始标签:结束标签:步长]开始标签:结束标签是左闭右开(左包含右不包含)下标----位置,默认是从0开始(从左到右)从右到左的下标,第一个下标为-1lst=......
  • 用python编写程序,使用筛选法查找并输出小于1000的所有素数
    #创建一个布尔数组,其中的值都是True,数组下标为i表示数字i是否为素数prime=[Trueforiinrange(1000)]#0和1不是素数,因此将它们的值设置为Falseprime[0]=Falseprim......
  • python - 操作sqlite
    1.连接数据库和创建游标importsqlite3conn=sqlite3.connect("test.db")cur=conn.cursor()2.建表sql="CREATETABLEtest_table(idINTEGERPRIMARYKEY,nam......
  • 一入python深似海,从此妹纸是路人(三)
    一、转义符1.转义字符\转义符2.字符串编码3.格式化输出"1.转义字符:首先是转义的意思"\n换行符print('hello\nworld')print('hello\\nworld')输出:hello\nworld......
  • Android RecyclerView异步更新数据导致的崩溃问题
          AndroidRecyclerView异步更新数据导致的崩溃问题 之前写极光即时通讯UI的时候,发现的问题,今天突发奇想,来分享给大家.问题症状:如果绑定的集合List中......
  • Python-pymysql如何向SQL语句中传参
    方法一:不传递参数##方式一、不传递参数id="01"name="语文"sql="select*fromcoursewherecourse_id='%s'andcourse_name='%s';"%(id,name)##......
  • 五种Python中字典的高级用法
    1.引言Python中的字典是一种非常有用的数据结构,它允许大家存储键值对。通常来说,字典灵活、高效且易于使用,是Python中最常用的数据结构之一。字典通常被用于统计频率、映射......
  • Python创建虚拟环境
    1、什么是虚拟环境虚拟环境的意义,就如同虚拟机一样,它可以实现不同环境中Python依赖包相互独立,互不干扰。 example:假设我们服务器中有两个项目,都是用到了一个第三方......
  • Python 并发
    1、并发与并行并行:多个程序同时运行并发:伪并行,看起来是同时并行,其实质是利用了多道技术无论是并行还是并发,在用户眼里看起来都是同时运行的,不管是线程还是进程,都是只是......
  • [oeasy]python0105_七段数码管_7_SEGMENT_数码管驱动_4511
    七位数码管回忆上次内容上次回顾了指示灯辉光管 并了解了驱动(driver)驱动就是控制设备工作的人(模块)  辉光管离我们的......