当前位置:硬件测评 > Python asyncio协程学习总结

Python asyncio协程学习总结

  • 发布:2023-10-06 01:03

实践环境

Python 3.6.2

什么是协程

协程(协程)一种计算机程序组件,通过允许挂起和恢复任务来生成用于非抢占式多任务处理的子例程。 Coroutine也可以简单理解为协作程序,是通过协作多任务实现并发的函数的变体(可以支持中断的函数)。

下面我们以日常生活场景为例来解释一下什么是协程。

假设A每天在家要做三件事:洗衣服(用洗衣机)、蒸饭(用电饭锅)、扫地(用扫地机器人)。这三个电器在完成任务后会发出不同的声音。告诉A某事已经完成。

这里,我们假设A的智商有问题。他每次都严格按照顺序做这三件事:先洗衣服,然后蒸饭,最后开始扫地。

接下来我们用一段简单的代码来模拟上面的整个过程,并记录一下所花费的时间。用三个简单的普通函数分别模拟以上三件事,如下:

导入时间
从日期时间导入日期时间
def do_washing():
print(www.sychzs.cn(), ':开始洗衣服')
time.sleep(3) # 洗衣服 # 用程序sleep来模拟这个过程,不用关心时间。
print(www.sychzs.cn(), ':通知A某些衣服已经洗好了')
def steame_rice():
print(www.sychzs.cn(), ':开始蒸饭')
time.sleep(5) # 米饭
print(www.sychzs.cn(), ':通知A某米蒸好了')
def do_clearing():
print(www.sychzs.cn(), ':开始扫地')
time.sleep(2) # 扫地
print(www.sychzs.cn(), ':通知A某个地方已被扫描')
如果 __name__ == '__main__':
开始时间 = time.time()
do_washing()
steame_rice()
do_clearing()结束时间 = time.time()
print("扫地+蒸饭+洗衣服总时间:", endTime - startTime)

程序输出:

2023-04-09 23:33:50.001204 :开始洗衣服
2023-04-09 23:33:53.002765:衣服洗好了
2023-04-09 23:33:53.002765:开始蒸米饭
2023-04-09 23:33:58.013337: 通知A某米蒸好了
2023-04-09 23:33:58.013337:通知A开始扫地
2023-04-09 23:34:00.024784:通知A某地已被扫过
扫地+蒸饭+洗衣服总时间:10.023579835891724

直到有一天,A的一位朋友来到他家。在体验了自己“高效”的工作效率后,他建议不要等所有事情完成后再做下一步事情。 A听后虚心接受,并告诉自己要开始养成新的习惯。

第二天,A开始改变自己。将衣服扔进洗衣机,启动机洗程序后,他就去洗米、蒸米。电饭锅开始蒸饭后,他去擦地板。

接下来我们稍微修改一下上面的代码,来模拟上面的过程,并记录下整个过程的耗时,如下:

导入时间
从日期时间导入日期时间
导入异步
异步 def do_washing():
print(www.sychzs.cn(),':开始洗衣服')
等待 asyncio.sleep(3)
print(www.sychzs.cn(),':通知A某些衣服已经洗好了')
异步 def do_clearing():
print(www.sychzs.cn(), ':开始扫地')
等待 asyncio.sleep(5)
print(www.sychzs.cn(), ':通知A某个地方已被扫描')
异步 def steame_rice():
print(www.sychzs.cn(), ':开始蒸饭')
等待 asyncio.sleep(2)
print(www.sychzs.cn(), ':通知A某米蒸好了')任务=[
do_washing(),
steame_rice(),
do_clearing()
]
如果 __name__ == '__main__':
循环 = asyncio.get_event_loop()
开始时间 = 时间.time()
www.sychzs.cn_until_complete(asyncio.wait(任务))
循环.close()
结束时间 = time.time()
print("扫地+蒸饭+洗衣服总时间:", end_time - start_time)

程序输出:

2023-04-09 23:35:17.422790 :开始扫地
2023-04-09 23:35:17.422790:开始蒸米饭
2023-04-09 23:35:17.422790 :开始洗衣服
2023-04-09 23:35:19.427500:通知A某米蒸好了
2023-04-09 23:35:20.427813:通知A某些衣服已经洗好了
2023-04-09 23:35:22.429780:通知A某地已被扫过
扫地+蒸饭+洗衣服总时间:5.0069899559021

不得不表扬A先生进步很大。与之前相比,这一次的时间缩短了近一半。

以上代码是协程的简单实现,充分体现了协程的三个特点:

  1. 多任务并行:A同时完成3个任务——分别代表3个协程。
  2. 异步任务:3个任务中,没有一个需要A监视直到完成。每个任务开始后,A 可以离开去做其他任务。
  3. 协作(非抢占):每个任务能否“占领”A取决于A是否正在被其他任务“占领”,即是否有任务主动“让出”A,而不是被“抢占”更像是谈判。

既然有了线程,为什么还需要协程?

协程是从用户角度的抽象。操作系统没有这个概念。其主要思想是在用户态实现调度算法,用少量的线程完成大量任务的调度。

与线程相比,协程有以下优点:

  • 减少内存使用

    协程的创建成本远低于线程。它们可以设计得非常小,小到KB级别,这样就大大减少了内存的使用。因此,当内存资源有限时,可以创建更多的协程来实现更高的并发。

  • 减少上下文切换开销,节省CPU资源

如上图所示,线程之间的切换请求是由系统内核实现的,而协程之间的切换可以由用户自由控制,即由用户态代码完成,这大大提高了避免了系统内核因层级线程上下文切换而造成的CPU资源浪费。具体实现思路如下:

  1. 尽可能减少可执行线程的数量,这样切换的次数必然会少

  2. 尽可能让线程处于运行状态,而不是阻塞放弃时间片

一个线程可以有多个协程。主要需要注意的是,一个线程中的多个协程都是串行的,无论CPU有多少个核心,因为协程本质上是一个函数。当一个协程正在运行时,其他协程必须暂停。在实际开发过程中,可以使用协程异步执行一些耗时的IO操作,比如写文件、耗时的IO请求等,以提高程序执行效率。

相关语法说明

接下来我们根据上面的例子来解释一下协程相关的语法。

async def do_washing()

使用 async def 语法定义协程函数 do_washing

协程函数示例:

async def func(param1, param2):
做东西()
等待 some_coroutine()

注:

  1. 使用 async def 语法定义的函数始终是协程函数,即使它们不包含 waitasync 关键词。

  2. 采用传统的函数调用方式,直接调用协程函数,函数不会立即执行,会产生类似RuntimeWarning: coroutine 'xxxx coroutine function' was never waiting的报警日志并返回一个协程对象。协程仅在事件循环运行时运行。

  3. await 挂起当前协程以等待可等待 (awaitable) 对象 - 协程函数或实现 __await__() 对象直到 waitable 对象返回结果。这个可等待对象可以简单理解为一个要执行的异步任务(通常是一个耗时的任务,比如开篇例子中使用的电饭锅)。

    注:

    1. await只能在协程函数内部使用。

    2. 程序遇到await关键字时,程序控制权将交给主程序,主程序会将其分配给其他协程。当可等待对象返回结果并且程序控制权仍被其他协程占用时,被挂起的协程仍然无法继续运行,直到获得程序控制权。对于这个结论,可以用下面的示例代码来验证:

      从日期时间导入日期时间
      导入异步
      异步 def do_washing():
      print(www.sychzs.cn(),':开始洗衣服')
      等待 asyncio.sleep(0.5)
      对于范围(10000)内的 i:
      如果我%4000==0:
      print('洗衣服')
      print(www.sychzs.cn(),':衣服洗好了')
      异步 def do_cooking():
      print(www.sychzs.cn(), ':开始煮饭')
      对于范围内的 i(100000):
      如果 i%20000 == 0:
      print('土豆饭')等待 asyncio.sleep(5)
      print(www.sychzs.cn(), ':电饭锅准备好了')
      任务=[
      做_烹饪(),
      do_washing()
      ]
      如果 __name__ == '__main__':
      循环 = asyncio.get_event_loop()
      www.sychzs.cn_until_complete(asyncio.wait(任务))
      循环.close()
      

      输出:

      2023-04-10 23:53:37.804727 :开始洗衣服
      2023-04-10 23:53:37.804727:开始煮饭
      煲仔饭
      煲仔饭
      煲仔饭
      煲仔饭
      煲仔饭
      洗衣服
      洗衣服
      洗衣服
      2023-04-10 23:53:38.310586:衣服洗好了
      2023-04-10 23:53:42.811876:电饭锅准备好了
      
asyncio.sleep(2)

在给定秒数后完成的协程 - 阻塞指定的秒数。 sleep函数还可以指定result参数,该参数将在协程完成时返回给调用者(默认返回None ) ,如下:

结果=等待asyncio.sleep(0.5,结果='任务完成')
print(result) #输出:任务完成

sleep 始终挂起当前任务以允许其他任务运行。您可以通过将秒数设置为 0(即 asyncio.sleep(0))来利用此功能,以提供允许其他任务运行的优化路径。长时间运行的函数可以使用它来避免调用函数时阻塞事件循环。

asyncio.get_event_loop()

获取当前上下文的事件循环并返回实现 AbstractEventLoop 接口的事件循环对象。如果当前上下文没有设置事件循环,并且当前策略没有指定创建事件循环,则会抛出异常。必须返回 None 以外的值。

www.sychzs.cn_until_complete(asyncio.wait(任务))

运行,直到 asyncio.wait(tasks) 完成。返回asyncio.wait(tasks)的运行结果,否则抛出异常。

www.sychzs.cn(coro, *, debug=False)

执行协程coro并返回结果。

该函数运行传递的协程,管理异步事件循环,终止异步生成器,并关闭线程池。

当同一线程中运行其他异步事件循环时,无法调用此函数。

如果 debugTrue,事件循环将在调试模式下运行。

此函数始终创建一个新的事件循环并在完成后关闭它。它应该用作 asyncio 程序的主要入口点,并且最好只调用一次。

示例:

async def main():
等待 asyncio.sleep(1)
打印('你好')
www.sychzs.cn(主())

3.7新功能。

asyncio.wait(任务)

wait函数及其完整参数列表定义如下

asyncio.wait(fs, *, 循环=无, 超时=无, return_when=ALL_COMPLETED)

并发运行fs可迭代对象中的可等待对象,并进入阻塞状态,直到满足return_when参数指定的条件(默认参数值为) 全部完成)。

请注意,aws 参数不能为空。

函数返回 Future 的集合:(已完成,待处理)

请注意,此函数不会引发asyncio.TimeoutError。当发生超时时,未完成的 Future 将在指定的秒数后返回。

return_when 指定此函数应何时返回。可选值如下:

  • 首次完成

    当任何可等待对象结束或取消时,

    函数将返回。

  • 第一个异常

    当任何可等待对象通过抛出异常结束时,

    函数将返回。当没有抛出异常时,它相当于ALL_COMPLETED

  • 全部完成

    当所有可等待对象结束或取消时,

    函数将返回。

其他协程示例

示例:Hello world携程

导入异步
异步定义 hello_world():
打印(“你好世界!”)
返回“你好世界”
# print(hello_world()) # RuntimeWarning: 协程 'hello_world' 从未被等待 #
循环 = asyncio.get_event_loop()
# 当 hello_world() 协程完成时返回的阻塞调用
res = www.sychzs.cn_until_complete(hello_world()) # 将协程对象传递给事件循环
print(res) # 输出:你好世界
循环.close()

python3.7版本,还可以使用新的APIwww.sychzs.cn来简化代码

导入异步
异步定义 hello_world():
打印(“你好世界!”)
返回“你好世界”www.sychzs.cn(hello_world())

示例:显示当前日期

使用 sleep() 函数

每 1 秒显示当前日期 5 秒的协程示例
导入异步
导入日期时间
异步 def display_date(循环):
结束时间 = 循环时间() + 5.0
而真实:
打印(日期时间.日期时间.now())
if (loop.time() + 1.0) >= end_time:
休息
等待 asyncio.sleep(1)
循环 = asyncio.get_event_loop()
# 当 display_date() 协程完成时返回的阻塞调用
循环.run_until_complete(显示日期(循环))
循环.close()

示例:链式协程

导入异步
异步定义计算(x,y):
print("计算 %s + %s ..." % (x, y))
等待 asyncio.sleep(1.0)
返回 x + y
异步 def print_sum(x, y):
结果=等待计算(x,y)
print("%s + %s = %s" % (x, y, 结果))
循环 = asyncio.get_event_loop()
循环.run_until_complete(print_sum(1, 2))
循环.close()

compute()链接到print_sum()print_sum()协程等待 compute()完成后返回结果

示例时序图

1 {IMG_1:Ahr0Chm6ly9pbwcymdizlmnuymxvz3Muy2JSB2CVMTU2OTQ1MI8ymdizmtuVMTU2OTQ1MDIZMDIZEWMC0ZNJC2MJCUC G5n/}

“任务”是在获取协程对象而不是任务时通过 www.sychzs.cn_until_complete() 方法创建的。

该图显示了控制流程,但没有准确描述内部如何工作。例如, sleep协程创建一个内部 future,它使用 www.sychzs.cn_later() in 1 在几秒钟内唤醒任务。

可用对象

一般来说,Python 协程的可等待对象包括协程函数或实现__await__()的对象。常见的等待对象包括:

  1. 使用

    定义的协程函数async def
  2. task对象,例如使用ASYNCIO.CREATE_TASK()或ASYNCIO.ensure_Future()任务对象创建的。

  3. Future 对象,例如使用 asyncio.Future() 创建的对象。

未来

Future 是对协程的封装,代表异步操作的最终结果——未来执行或不执行的任务的结果,其值将在未来计算。

类asyncio.Future(*,循环=无)

该类基本兼容concurrent.futures.Future

差异:

  • result()Exception() 不接受超时参数,如果 future 尚未完成,则会抛出异常。
  • 始终通过事件循环的 call_soon_threadsafe() 调用使用 add_done_callback() 注册的回调。
  • 该类与 concurrent.futures 中的 wait()as_completed() 相同 封装 功能不兼容。

该类不是线程安全的。

类法

  • 取消()
    取消 future 并安排执行回调

    如果未来已完成或取消,则返回False。否则,将 future 的状态修改为已取消,安排执行回调,并返回True

  • 取消()

    如果未来已取消,

    返回 True

  • 完成()
    如果 future 已完成,则返回 True

    完成表示结果可用或发生异常,或未来已被取消。

  • 结果()

    返回未来呈现的结果。

    如果未来已被取消,则会引发 CancelledError。如果未来的结果尚不可用,则会引发 InvalidStateError。如果 future 已经完成并且有异常,则会抛出该异常。

  • 异常()
    返回未来设置的异常。

    仅当future完成时才返回异常(如果没有设置异常则返回None)。如果 future 被取消,则会引发 CancelledError。如果未来尚未完成,则会引发 InvalidStateError

  • add_done_callback(fn)

    添加回调以在 future 完成时运行。

    使用 future 对象作为参数调用回调。如果调用时 future 已完成,请使用 call_soon() 调用回调。

    使用 functools.partial 将参数传递给回调。例如

    fut.add_done_callback(functools.partial(print, "Future:",lush=True)) 将调用 print("Future:", fut,lush=True)

  • remove_done_callback(fn)

​ 从“完成后调用”列表中删除回调的所有实例。

​ 返回已删除回调的数量。

  • set_result(结果)
    将未来标记为已完成并设置其结果。

    如果调用此方法时 future 已完成,则会引发 InvalidStateError

  • set_exception(异常)

    将未来标记为已完成并设置例外。

    如果调用此方法时 future 已完成,则会引发 InvalidStateError

示例:使用 Future 与 run_until_complete()

导入异步异步 def Slow_Operation(未来):
等待 asyncio.sleep(1)
future.set_result('未来已经完成!')
循环 = asyncio.get_event_loop()
未来 = asyncio.Future()
asyncio.ensure_future(slow_operation(future))
循环.run_until_complete(未来)
print(future.result()) # Future 已经完成!
循环.close()

协程函数负责计算(耗时1秒)并在以后存储结果。 run_until_complete()方法等待future的完成。

注:
run_until_complete() 方法内部使用 add_done_callback() 方法在 future 完成时收到通知。

Future类封装了可调用对象的异步执行

示例:使用 Future 与 run_forever()

可以使用 Future.add_done_callback() 方法以不同的方式编写前面的示例,以明确描述控制流:

导入异步
异步 def Slow_Operation(未来):
等待 asyncio.sleep(1)
future.set_result('未来已经完成!')
def 得到的结果(未来):
打印(未来.结果())
循环.stop()
循环 = asyncio.get_event_loop()
未来 = asyncio.Future()
asyncio.ensure_future(slow_operation(future))
future.add_done_callback(got_result)
尝试:循环运行_forever()
最后:
循环.close()

在本例中,future 用于将 slow_operation() 链接到 got_result():当 slow_o当操作()完成时,将调用 got_resull()得到结果

任务

类asyncio.Task(coro,*,循环=无)
安排协程的执行:将其封装在 future 中。 Task 是 Future 的子类。

task 负责在事件循环中执行协程。如果封装协程是由 future 生成的,则任务将阻塞封装协程的执行并等待 future 完成。当 future 完成并返回结果或异常时,封装协程的执行将重新启动并检索 future 的结果或异常。

事件循环使用协作调度:事件循环一次仅运行一个任务。如果其他事件循环在不同的线程中运行,则其他任务可以并行运行。当任务等待未来完成时,事件循环会执行一个新任务。

取消任务和取消未来之间是有区别的。调用 cancel() 会将 CancelledError 抛出到包装的协程中。仅当封装协程未捕获 CancelledError 异常或抛出 CancelledError 时,才会返回 cancelled()例外。 正确

如果待处理任务被销毁,其封装的协程将无法完成。这可能是一个错误并记录警告:

任务已被销毁,但正在等待处理!
任务: wait_for=>

请勿直接创建 Task 实例:使用 ensure_future() 函数或 AbstractEventLoop.create _task( ) 方法。

该类不是线程安全的。

类法

  • all_tasks(循环=无)
    返回给定事件循环的所有任务的集合。默认情况下,返回当前事件循环中的所有任务。

  • current_task(循环=无)
    返回给定事件循环中当前正在运行的任务。默认返回当前事件循环中的当前任务。

    当未在任务上下文中调用此函数时,

    返回 None

  • 取消()
    请求取消任务

    安排在事件循环的下一次迭代中将 CancelledError 抛出到封装的协程中。然后,协程有机会使用 try/ except/finally 来清理甚至拒绝请求。

    Future.cancel()不同,这并不能保证任务将被取消:异常可能会被捕获并采取行动,从而延迟任务的取消或完全阻止任务的取消。该任务还可能返回一个值或引发不同的异常。

    调用此方法后,cancelled()不会立即返回True(除非任务已被取消)。当包装的协程因CancelledError异常终止时,任务将被标记为已取消(即使cancel()尚未被调用)。

  • get_stack(*,限制=无)

    返回此任务协程的堆栈帧列表。

    如果协程未完成,则返回其暂停的堆栈。如果协程成功完成或被取消,则返回一个空列表。如果协程异常终止,则返回回溯帧列表。

    堆栈帧始终按从最旧到最新的顺序排列。

    可选 limit 给出返回的最大帧数;默认情况下,将返回所有可用的帧。它的含义根据是否返回堆栈或回溯而有所不同:返回堆栈的最新帧,但返回回溯的最旧帧(这与回溯模块的行为一致)。

    由于我们无法控制的原因,对于挂起的协程仅返回一个堆栈帧。

  • print_stack(*,限制=无,文件=无)

    打印此任务协程的堆栈或回溯。

    get_stack() 检索的帧生成类似于回溯模块的输出。 limit参数传递给get_stack()file参数是将输出写入的 I/O 流;默认情况下,输出写入 sys.stderr

示例:并行执行任务

并行执行 3 个任务(A、B、C)

导入异步
异步 def 阶乘(名称,数字):
f=1
对于范围(2,数字+1)中的i:
print("任务 %s: 计算阶乘(%s)..." % (name, i))
等待 asyncio.sleep(1)
f*=i
print("任务 %s: 阶乘(%s) = %s" % (名称, 数字, f))
循环 = asyncio.get_event_loop()
循环.run_until_complete(asyncio.gather(
阶乘(“A”,2),
阶乘(“B”,3),
阶乘(“C”,4),
))
循环.close()

输出:

任务 B:计算阶乘 (2)...
任务 C:计算阶乘(2)...
任务 A:计算阶乘(2)...
任务 B:计算阶乘(3)...
任务 C:计算阶乘(3)...
任务 A:阶乘(2) = 2
任务 B:阶乘(3) = 6任务 C:计算阶乘(4)...
任务 C:阶乘(4) = 24

任务在创建时会自动调度执行。所有任务完成后,事件循环将停止。

任务功能

注:

在以下函数中,可选的循环参数允许显式设置底层任务或协程使用的事件循环对象。如果未提供,则使用默认事件循环

  • www.sychzs.cn_completed(fs,*,循环=无,超时=无)

    在等待时返回一个 Future 实例的迭代器。

    如果在所有 Future 完成之前发生超时,则会引发 asyncio.TimeoutError

    示例:

    对于 as_completed(fs) 中的 f:
    result = Yield from f # 'yield from' 可能会提高
    #使用结果
    

    注:
    未来的 f 不一定是 fs

    的成员
  • asyncio.ensure_future(coro_or_future,*,循环=无)

    安排协程对象的执行:在其封装在Future中。返回一个Task对象。

    如果参数是Future,则直接返回。

    版本3.4.4中新增

    版本3.5.1变更: 函数接受任何可等待对象。

  • asyncio.async(coro_or_future, *, loop=None)
    废弃的ensure_future()的别名

    版本 3.4.4开始废弃

  • asyncio.wrap_future(future, *, loop=None)

    concurrent.futures.Future对象封装在Future对象中。

  • asyncio.gather(*coros_or_futures, loop=None, return_exceptions=False)

    返回来自给定协程对象或future的future聚合结果。

    所有future必须共享相同的事件循环。如果所有task都成功完成,那么返回的future结果就是结果列表(按照原始序列的顺序,不一定是结果到达的顺序)。如果return_exceptions为true,则task中的异常将被视为成功的结果,并收集在结果列表中;否则,第一个抛出的异常将立即传递给返回的future。

    取消:如果外部Future被取消,则所有子项(尚未完成)也将被取消。如果任何子项被取消,这将被视为引发CancelledError错误——在这种情况下,外部Future不会被取消。(这是为了防止取消一个子项而导致其他子项被取消。)

  • asyncio.iscoroutine(obj)
    如果obj是一个协程对象,该对象可能基于生成器或async def协程,则返回True

  • asyncio.iscoroutinefunction(func)
    如果func被判断为协程函数,则返回True,协程函数可以是被修饰的生成器函数或async def函数。

  • www.sychzs.cn_coroutine_threadsafe(coro, loop)

    向给定的事件循环提交一个协程对象。

    返回concurrent.futures.Future以访问结果。

    该函数被从不同于运行事件循环线程的线程调用。用法:

    # Create a coroutine
    coro = asyncio.sleep(1, result=3)
    # Submit the coroutine to a given loop
    future = www.sychzs.cn_coroutine_threadsafe(coro, loop)
    # Wait for the result with an optional timeout argument
    assert future.result(timeout) == 3
    

    如果在协程中引发异常,则会通知返回的future。它还可以用于取消事件循环中的task:

    try:
    result = future.result(timeout)
    except asyncio.TimeoutError:
    print('The coroutine took too long, cancelling the task...')
    future.cancel()
    except Exception as exc:
    print('The coroutine raised an exception: {!r}'.format(exc))
    else:
    print('The coroutine returned: {!r}'.format(result))
    

    注意:
    与模块中的其他函数不同,run_coroutine_threadsafe() 要求显式传递loop参数。

    版本3.5.1中新增

  • coroutine asyncio.sleep(delay, result=None, *, loop=None)

    创建一个给定秒数后完成的协程--阻塞指定的秒数。sleep函数还可以指定result参数,协程完成时将该参数值返回给调用者(默认返回None

  • asyncio.shield(arg, *, loop=None)
    等待future,保护它不被取消。

    语句:

    res = yield from shield(something())
    

    等价于:

    res = yield from something()
    

    除非包含它的协程被取消,否则在something()中运行的任务不会被取消。从something()的视角来看,并没法生取消。但是它的调用者仍然被取消,所以yield from表达式仍然会引发CancelledError。注意:如果通过其他方式取消了something(),这仍然会取消shield()

    如果你想完全忽略取消(cancellation,不推荐),你可以将shield()try/except子句结合使用,如下所示:

    try:
    res = yield from shield(something())
    except CancelledError:
    res = None
    
  • coroutine asyncio.wait(futures, *, loop=None, timeout=None, return_when=ALL_COMPLETED)

    等待futures序列参数给定的Future和协程对象执行完成。协程将被封装在task中。返回两个Future集:(done,pending)

    • futures序列参数不能为空。

    • timeout参数可用于控制返回前等待的最大秒数。timeout可以是intfloat类型。如果未指定timeout参数或参数值为空,则没有等待时间限制,即永不超时。

    • return_when指示此函数何时返回。它必须是concurrent.futures模块的以下常量之一:

      • FIRST_COMPLETED 当任何future完成或被取消时,函数将返回。
      • FIRST_EXCEPTION 当任何future因为引发异常而结束时,函数将返回。如果没有future引发异常,那么它相当于ALL_COMPLETED
      • ALL_COMPLETED当所有future结束或被取消时,函数将返回。

    这个函数是一个协程。

    用法:

    done, pending = yield from asyncio.wait(fs)
    

    注意
    这不会引发asyncio.TimeoutErrorpending集合中存放的是发生超时时未完成的future。

  • coroutine asyncio.wait_for(fut, timeout, *, loop=None)

    等待单个future或协程对象完成直到发生超时(如果超时限制的话)。如果timeoutNone,则一直等待直到future完成。

    协程将被封装在Task中。

    函数返回Future或协同程序的结果。当发生超时时,将取消task并抛出asyncio.TimeoutError。为了避免任务取消,请将其封装在shield()中。

    如果取消wait,那么future fut也将被取消。

    该函数为一个协程,用法:

    result = yield from asyncio.wait_for(fut, 60.0)
    

参考连接:

https://www.sychzs.cn/A/gGdXlLmmd4/

相关文章