Python中的异步for Loop

本教程将提供关于Python中异步for 循环的完整细节。我们将讨论异步函数、异步for 循环和sleep 概念。

接下来,我们将讨论Python库asyncio 和运行异步代码所需的函数。最后,我们将看到Python中的几个例子来充分理解这个概念。

Python中的异步函数

异步函数有助于运行繁重的任务(如批处理程序,也许我们对在后台运行进程感兴趣),与同一程序的其他函数并行。当函数之间不相互依赖或不完全依赖时,就有可能并行地运行函数。

同步函数一旦完成任务就会返回控制权,而异步函数则返回控制权以并行运行其他函数/代码,并在一段时间后取回控制权。这样一来,不仅繁重的任务得以完成,许多其他任务也得以并行完成。

从技术上讲,同步函数阻断了main ,而异步函数的执行没有阻断main 。这样一来,main 函数可以并行地运行多个异步函数。

Python中的异步for 循环

对于同步循环,它们的执行没有任何暂停/给予控制;然而,为了使它们成为异步的,我们必须在一些异步函数中定义它们。另外,我们需要在这个过程中休眠一段时间,以便将控制权交给其他函数。

使用sleep 语句

一个进程/线程/函数可能会休眠一段时间;你可以认为这是一个中断。然而,其目的是为了在一定时间内失去控制。

因此,其他函数会得到控制权。在一段时间后,控制权又回到了原位,而函数又恢复了。

现在,是时候在Python中实现了。我们将逐步讨论语法部分,在最后,我们将展示完整的代码。

Python库和函数

asyncio 是Python中的一个库,用来编写使用async/await 语法的并发程序/函数。async 是在每个函数开始时使用的关键字(创建异步函数)。

语法是:

async def fun_a(t):

这里添加了async ,以声明这个函数是一个异步函数。

sleep 函数可以在一定时间内暂停执行一个Coroutine。Coroutine是在执行过程中构成流水线结构的进程/函数。

这个函数通过await 关键字自愿离开CPU去做另一个合作任务。sleep 函数的语法是:

await asyncio.sleep(1)

注意:调用每一个异步函数都需要关键字await ,无论它是来自库还是用户定义的函数。

await 关键字将控制权返回到事件循环中。你可以考虑,如果一个异步函数用await 命令调用,sleep 语句(在for 循环内)控制合作进程,直到睡眠。

gather 函数结合了多个合作进程(技术上是做一个coroutine),作为一个单元运行。这个函数按照gather 调用中的函数顺序返回一个结果的元组。

语法是:

results = await asyncio.gather(fun_a(5), fun_b(5))

在这里,我们要把fun_afun_b 做成一个流水线,这样它们就可以同时运行。

事件循环是每个异步应用程序的主要成分。事件循环运行异步函数。

get_event_loop() 方法检查set_event_loop 是否还没有被调用,它将创建一个事件循环并将其设置为当前状态。语法是::

my_loop = asyncio.get_event_loop()

如果在循环已经创建的情况下第二次执行这个命令,它将不做任何事情。然而,在第一次调用时,没有创建循环;因此,它将创建一个异步循环。

如果get_event_loop() ,返回的循环是异步的,那么run_until_complete() ,用于同时运行事件循环。语法是:

my_loop.run_until_complete(main())

如果main 函数是异步的,该语句将并发地运行代码。

异步代码

在对概念和运行异步函数/程序/进程所需的Python库有了清晰的概念后,现在是时候看看一个完整的编码例子了:

import asyncio
async def fun_a(t):
    for i in range(t):
        print("fun_a", end=' ')
        await asyncio.sleep(1)
    return 1
async def fun_b(t):
    for i in range(t):
        print("fun_b", end=' ')
        await asyncio.sleep(1)
    return 2
async def main():
    results = await asyncio.gather(fun_a(5), fun_b(5))
    print(results)
my_loop = asyncio.get_event_loop()
my_loop.run_until_complete(main())

在这段代码中,在顶部(第一行),我们正在导入asyncio 库。这个库有一个调用异步函数并发运行的必要函数;它们已经用语法讨论过了。

接下来,我们有两个异步函数–fun_afun_b ,我们想让它们同时运行。同样,我们想从main函数中调用异步函数。因此,main也被创建为一个异步函数。

另外,请注意,我们向我们的函数传递了5 ,以便在其内部运行五次循环。所以稍后,你可以看到输出,并得到循环没有完全运行的想法;每个都进入睡眠状态,并将控制权交给其他函数。

我们将在输出后重复这一点。

main 函数里面,我们已经调用了gather 函数,并传递了我们的异步函数,以便它们可以并行运行。gather 函数返回一个元组,有两个从我们的目标异步函数返回的值。

我们终于来到了最后两行。在最后第二行,我们调用了get_event_loop 函数来创建一个循环。在最后一行,使用我们的循环,我们调用了run_until_complete 函数,开始异步运行我们的main 函数。

这段代码的输出是:

fun_a fun_b fun_a fun_b fun_a fun_b fun_a fun_b fun_a fun_b [1, 2]

首先,注意我们的循环并不像传统的代码那样完全运行,相反,两个循环都在并发地运行。你可以看到两个函数的结果print 语句。

最后,[1, 2]main 函数从我们的异步函数中收到的元组。12 是由我们的异步函数返回的,并按照我们在gather 函数中编写这些函数的顺序排列。