您的位置:

Python 异步编程——asyncio和await

asyncio 模块。asyncio模块具有优秀的特性,允许我们编写更高效的 Python 异步应用。我们将探讨如何在 Python 中管理异步事件循环。在深入探讨这个主题之前,让我们先了解一下什么是异步编程。

什么是异步编程?

在同步编程中,方法被编写成一次执行一个任务。如果一个函数依赖于另一个函数的输出,它必须等待该函数的执行完成。程序实际上是停止的,直到函数完成它的执行。这意味着一次可以执行一个程序。

这降低了程序的速度,因为它被迫停止并等待一些事情完成。系统中有许多进程器可用,因此做其他任务而不是理想的 sit 是对资源的浪费。

为了克服这一点,异步编程概念开始发挥作用。它的行为不同;它也需要一次执行一次。但是系统可能不会等到执行完毕再继续下一步。

这意味着,如果程序将执行另一项任务,而前一项任务尚未完成并仍在其他地方运行,则处理器并不理想。

在本教程中,我们将解释为什么我们需要这样一种类型的编程。

什么是异步输入输出?

asyncio 是一个 Python 库,用于使用异步/等待运行并发代码。它是 Python 异步框架的基础,提供连接库、网络和 web 服务器、数据库分布式任务队列、高性能等。

该模块提供了围绕事件循环工作的框架,并且还处理输入/输出和系统事件等事情。

协同工作和任务

asyncio 是一个 Python 库,用于使用异步/等待运行并发代码。它是 Python 异步框架的基础,提供连接库、网络、网络服务器、数据库分布式任务队列、高性能等。

该模块提供了围绕事件循环工作的框架,并处理输入/输出和系统事件等事务。

示例- 1


import asyncio
async def main():
    print ("Waiting 5 seconds. ")
    for _ in range(5):
        await asyncio.sleep(1)
        print ("Hello")
    print ("Finished waiting.")
asyncio.run(main())

输出:

Waiting 5 seconds. 
Hello
Hello
Hello
Hello
Hello
Finished waiting.

解释-

在上面的代码中-

  • 我们已经导入了 asyncio模块来访问 Python 异步功能。
  • 然后创建一个 primary() 函数,并在前面写 async 关键字。这将允许程序异步运行任务。
  • 我们使用 for循环并调用sleep()方法,这迫使我们等待 1 秒钟。
  • 程序一秒钟后打印“你好”。
  • 程序应该有一个。运行()功能以及一个。main() 功能。

我们还可以安排任务或对象来绑定协程并帮助它们运行。让我们理解下面的例子。

示例- 2


import asyncio
import time

async def execute(delay, value):
    await asyncio.sleep(delay)
    print(value)

async def main():
    print(f"started at {time.strftime('%X')}")

    await execute(1, 'hello')
    await execute(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

输出:

started at 11:11:54
hello
world
finished at 11:11:57

解释-

在上面的代码中,

  • 我们已经导入了 asyncio 和时间模块。
  • 然后我们用延迟和值参数定义了 execute() 函数。它使用睡眠()方法打印延迟时间。
  • 在 main() 函数中,我们传递了两个参数:第一个是延迟时间,第二个是要打印的值。
  • 程序开始执行并打印准确的执行时间,打印“你好”,然后等待两秒钟,打印“世界”并停止。

现在,让我们对上面的代码进行一些更改,并查看结果。

示例- 3 创建任务


async def execute(delay, value):
    await asyncio.sleep(delay)
    print(value)

async def main():
    # Using asyncio.create_task() method to run coroutines concurrently as asyncio
    task1 = asyncio.create_task(
        execute(1, 'hello'))

    task2 = asyncio.create_task(
        execute(2, 'world'))

    print(f"started at {time.strftime('%X')}")

    # Wait until both tasks are completed (should take
    # around 2 seconds.)
    await task1
    await task2

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

输出:

started at 15:43:30
hello
world
finished at 15:43:32

我们可以看到它比前一个程序快 1 秒。 create.task() 方法将在事件循环中运行,并将结果放入任务中。我们已经安排了这两个任务,并使用等待返回它们。

用 Python 管理异步事件循环

Asyncio 还用于管理异步事件循环。事件循环是运行异步函数和回调的对象。当我们想要执行协程时,当我们运行 asyncio.run() 方法时,事件对于异步函数来说是至关重要的;自动创建事件循环对象。为了实现更高级的服务器,我们需要对事件循环的低级访问。我们需要直接处理事件循环的内部。

事件循环具有以下特征。

  • 它可以注册、执行和取消延迟调用(异步函数)
  • 它可以为通信创建客户机和服务器传输
  • 它可以为与另一个程序的通信创建子过程和传输。
  • 将函数调用委托给线程池。

让我们看看下面的例子。

示例-


import asyncio

async def speech_async():
    print('This is a asynchronicity!')

loop = asyncio.get_event_loop()
loop.run_until_complete(speech_async())
loop.close()

输出:

This is a asynchronicity!

事件循环从获取 asyncio.get_event_loop() 开始,调度并运行异步任务,当我们完成运行时关闭事件循环。

用 Python 中的流读写数据

asyncio模块提供流,用于执行高级网络输入/输出。它可以充当网络请求的服务器。它最适合于长时间运行的网络操作,其中应用阻塞等待一些其他资源返回结果。

asyncio 有两个类,StreamReader 和 StreamWriter 。这些类用于高级别的网络读写。

要从网络读取,我们需要使用asyncio . open _ connection()打开网络。我们将使用流读取器和流写入器对象函数返回元组。阅读()和。将()方法写入每个连接。

asyncio.start_server ()方法用于接收来自远程主机的连接。该函数以回调函数 client_connected_cb 为参数。每当函数收到请求时都会调用它。

Python 中的同步任务

我们之前已经讨论过,异步程序是分开运行的,但是有时我们会希望相互通信。asyncio模块为我们提供了一个队列和各种其他方法来建立任务之间的同步。

下面我们来了解一下下面的实现方法。

  • 队列- 异步队列便于异步函数排列 Python 对象,以供其他异步函数使用。例如——工作负载分布在行为上的函数之间。
  • 同步原语-asyncio 的特性锁、事件、条件和信号量充当了传统 Python 的对应物。

这里有一点要时刻记住,这些方法不是线程安全的。对于在同一事件循环中运行的异步任务,这不是问题。但是我们需要使用线程模块在任务之间共享信息。

什么时候使用异步编程?

在下面的场景中,我们可以使用异步编程。

  • 当我们想要快速完成工作时。
  • 延迟包括等待输入/输出(磁盘或网络)操作,而不是计算。
  • 当许多输入/输出操作同时发生时。

asyncio模块允许我们并行执行多个任务,并高效地迭代它们,而不会阻塞应用的其余部分。

下面给出了一些任务,它们可以很好地与 asyncio 配合使用。

  • 刮网。
  • 网络服务(网络服务器和框架)
  • 同步数据库

Asyncio 中的几个重要函数

下面是异步编程时使用的一些基本方法。

运行异步程序

  • asyncio.run(coro,* debug = False)-*此功能用于阻止 执行延迟*** 秒。它挂起当前任务,并允许另一个任务运行。延迟是一个显示秒数的参数。

示例-


async def main():
    await asyncio.sleep(1)
    print('hello')
asyncio.run(main())

创建任务

  • *create_task(coro, name = None)-该功能将 Coroutines 包装成一个 task,安排**执行。它返回任务对象。

示例-


async def coro():
    ...

# In Python 3.7+
task = asyncio.create_task(coro())
...
task = asyncio.ensure_future(coro())

睡眠

  • *睡眠(延迟,结果=无,循环=无)- 此功能用于阻止执行延迟执行**秒。它挂起当前任务,并允许其他任务运行。延迟是一个显示秒数的参数。

示例-


import asyncio
async def main():
    for _ in range(3):
        await asyncio.sleep(1)
        print ("Hello")
asyncio.run(main())

超时设定

  • *协同工作等待(aw,超时,循环=无)- 该功能用于等待 aw(协同工作自动安排为任务)唤醒超时完成。

示例-


async def myfunc():
    # Sleep for ten minutes
    await asyncio.sleep(600)
    print('hello!')

async def main():
    # Wait for at most 1 second
    try:
        await asyncio.wait_for(myfunc(), timeout=1.0)
    except asyncio.TimeoutError:
        print('timeout!')

asyncio.run(main())

结论

本教程包括使用 Python asyncio模块进行异步编程的概念。当我们使用上下文切换时,asyncio 为我们提供了对何时上下文的编程控制。这意味着我们可以处理线程编程中出现的许多复杂问题。

它是一个强大而有价值的工具,但仅适用于异步类型编程。我们已经用它们各自的例子讨论了协程和任务。我们还讨论了在 Python 中管理事件循环和用流读写数据。它还包括必要的方法。