乐趣区

关于程序员:Python-异步-异步上下文管理器17

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

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

退出移动版