当前位置: 首页 > 面试题库 >

asyncio.ensure_future与BaseEventLoop.create_task与简单协程?

越嘉茂
2023-03-14
问题内容

我看过一些关于asyncio的基本Python 3.5教程,以各种方式进行相同的操作。在此代码中:

import asyncio

async def doit(i):
    print("Start %d" % i)
    await asyncio.sleep(3)
    print("End %d" % i)
    return i

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    #futures = [asyncio.ensure_future(doit(i), loop=loop) for i in range(10)]
    #futures = [loop.create_task(doit(i)) for i in range(10)]
    futures = [doit(i) for i in range(10)]
    result = loop.run_until_complete(asyncio.gather(*futures))
    print(result)

上面定义futures变量的所有三个变体都可以达到相同的结果。我可以看到的唯一区别是,在第三个变体中,执行是乱序的(在大多数情况下不重要)。还有其他区别吗?在某些情况下,我不能只使用最简单的变体(协程的简单列表)吗?


问题答案:

实际信息:

从Python 3.7开始,为此添加了asyncio.create_task(coro)高级功能。

您应该使用它代替其他从coroutime创建任务的方法。但是,如果您需要从任意等待中创建任务,则应使用asyncio.ensure_future(obj)

旧信息:

ensure_futurecreate_task

ensure_future是一种Task从创建的方法coroutine。它基于参数(包括create_task对协程和类似未来的html" target="_blank">对象使用of)以不同的方式创建任务。

create_task是的抽象方法AbstractEventLoop。不同的事件循环可以以不同的方式实现此功能。

您应该ensure_future用来创建任务。create_task仅在要实现自己的事件循环类型时才需要。

更新:

@
bj0指向Guido对此主题的回答:

的要点ensure_future()是,如果您有可能是协程或a的东西Future(后者包含a,Task因为这是的子类Future),并且您希望能够在其上调用仅在其上定义的方法Future(可能是唯一的)有用的示例cancel())。当它已经是Future(或Task)时,则不执行任何操作;当它是一个协程时,它将它
包裹 在一个Task

如果您知道有一个协程,并且希望对其进行调度,则使用的正确API是create_task()。唯一应该调用的时间ensure_future()是在提供接受协程或a的API(如asyncio自己的大多数API)时,Future您需要对其进行一些操作,要求您拥有a
Future

然后:

最后,我仍然相信这ensure_future()是一个很少需要的功能的适当模糊的名称。从协程创建任务时,应使用适当命名的
loop.create_task()。也许应该为此起别名 asyncio.create_task()

我很惊讶
我一直使用的主要动机ensure_future是,与loop的成员相比,它是更高级别的函数create_task(讨论中包含了诸如addasyncio.spawn或的想法asyncio.create_task)。

我还可以指出,在我看来,使用可以处理任何Awaitable而非协程的通用函数非常方便。

但是,Guido的答案很明确: “从协程创建任务时,应使用名称正确的loop.create_task()

什么时候应该将协程包裹在任务中?

将协程包装在任务中-是一种在后台启动协程的方法。例子如下:

import asyncio


async def msg(text):
    await asyncio.sleep(0.1)
    print(text)


async def long_operation():
    print('long_operation started')
    await asyncio.sleep(3)
    print('long_operation finished')


async def main():
    await msg('first')

    # Now you want to start long_operation, but you don't want to wait it finised:
    # long_operation should be started, but second msg should be printed immediately.
    # Create task to do so:
    task = asyncio.ensure_future(long_operation())

    await msg('second')

    # Now, when you want, you can await task finised:
    await task


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

输出:

first
long_operation started
second
long_operation finished

您可以替换asyncio.ensure_future(long_operation())为只是await long_operation()感觉有所不同。



 类似资料:
  • 本文向大家介绍简单谈谈apache与nginx,包括了简单谈谈apache与nginx的使用技巧和注意事项,需要的朋友参考一下 一、 关于Apache与Nginx的优势比较     不断有人跟我说Nginx比Apache好、比Apache快之类。Nginx更主要是作为反向代理,而非Web服务器使用。我翻译过一本关于反向代理的技术书籍,同时精通Apache API开发,对Nginx和Apache的工

  • 问题内容: 我想学习PHP,并希望获得有关OOP和过程的想法。我还阅读了其他有关OOP与程序的博客和教程,但我仍然不理解这种方法。 OOP与程序 我应该学习哪个? 代码有什么区别?有什么影响? PHP框架如何帮助OOP?(我想学习CodeIgniter) 程序是否需要框架? 我真的很想知道两者的代码区别,我对OOP的理解是您创建了类似的类并且可以访问。(我不知道是否正确)。 谢谢! 问题答案: 背

  • 这是我的第一个帖子,但我需要一些帮助,这是我的错误: 这是我的gradle密码

  • 本文向大家介绍关于JSON与JSONP简单总结,包括了关于JSON与JSONP简单总结的使用技巧和注意事项,需要的朋友参考一下 一、什么是json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3

  • channel与协程间通信 虽然已经构建了基于yield的半协程,之前所有讨论都集中在单个协程,我们可以再深入一步,构造带有阻塞语义的协程间通信原语--channel,这里按照Golang的channel来实现; playground By default, sends and receives block until the other side is ready. This allows go

  • 要想团队协作使用Git,就需要用到Git协议。 3.1.1. Git支持的协议 首先来看看数据交换需要使用的协议。 Git提供了丰富的协议支持,包括:SSH、GIT、HTTP、HTTPS、FTP、FTPS、RSYNC及前面已经看到的本地协议等。各种不同协议的URL写法如表15-1所示。 表 15-1:Git支持的协议一览表 协议名称 语法格式 说明 SSH协议(1) ssh://[user@]ex