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_a
和fun_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_a
和fun_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
函数从我们的异步函数中收到的元组。1
和2
是由我们的异步函数返回的,并按照我们在gather
函数中编写这些函数的顺序排列。