Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python asyncio.Sure_future vs.BaseEventLoop.create_task vs.simple Corroutine?_Python_Python 3.x_Python 3.5_Coroutine_Python Asyncio - Fatal编程技术网

Python asyncio.Sure_future vs.BaseEventLoop.create_task vs.simple Corroutine?

Python asyncio.Sure_future vs.BaseEventLoop.create_task vs.simple Corroutine?,python,python-3.x,python-3.5,coroutine,python-asyncio,Python,Python 3.x,Python 3.5,Coroutine,Python Asyncio,我已经看过几个关于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()

我已经看过几个关于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)
上面定义
期货
变量的所有三个变量都获得相同的结果;我能看到的唯一区别是,对于第三个变体,执行是无序的(在大多数情况下,这不重要)。还有其他区别吗?在某些情况下,我是否不能只使用最简单的变体(普通的协同程序列表)?

create\u task()
  • 接受协同程序
  • 返回任务
  • 它在循环的上下文中被调用

确保未来()
  • 接受未来,合作,等待的对象
  • 返回任务(如果未来已通过,则返回未来)
  • 如果给定的参数是一个协同程序,它将使用
    create\u task
  • 可以传递循环对象
正如您所看到的,create_任务更加具体


async
功能,无需创建任务或确保未来 简单调用
async
函数返回协同路由

>>> async def doit(i):
...     await asyncio.sleep(3)
...     return i
>>> doit(4)   
<coroutine object doit at 0x7f91e8e80ba0>
异步def doit(i): ... 等待asyncio.sleep(3) ... 返回i >>>doit(4) 而且由于引擎盖下确保(
sure_future
)args是未来,因此明确地说
sure_future
是冗余的

类似问题

实际信息: 从Python3.7开始
asyncio.create_task(coro)
用于此目的的高级函数

您应该使用它来代替从coroutimes创建任务的其他方法。但是,如果需要从任意可等待项创建任务,则应使用
asyncio。确保未来(obj)


旧信息:
确保未来
vs
创建任务
确保未来是一种创建的方法。它根据参数以不同的方式创建任务(包括使用
create\u task
来创建协同程序和类似未来的对象)

create\u task
AbstractEventLoop
的一种抽象方法。不同的事件循环可以以不同的方式实现此功能

您应该使用
确保未来
创建任务。只有当您要实现自己的事件循环类型时,才需要
create_task

Upd:

@bj0在这个话题上指出:

sure_future()
的要点是,如果你有什么东西可以 可以是协同程序,也可以是
未来
(后者包括
任务
,因为 这是
Future
)的子类,您希望能够调用一个方法 仅在
Future
上定义(可能是唯一有用的 示例为
cancel()
)。当它已经是
未来
(或
任务
)时 什么也不做;当它是一个协同程序时,它将它包装在一个
任务中

如果你知道你有一个合作项目,你想把它安排好, 正确使用的API是
create\u task()
。唯一一次你应该 在提供API时调用
确保未来()
是 asyncio自己的API),它接受协同路由或
未来
和 你需要对它做点什么,这需要你有一个
未来

后来:

最后,我仍然相信
确保未来()
是一个合适的选择 一个很少需要的功能的模糊名称。创建时 来自协同程序的任务您应该使用适当命名的
循环。创建任务()
。也许应该有一个别名
asyncio.create_task()

我很惊讶。我一直使用
确保未来
的主要动机是,与循环的成员
创建任务
相比,它具有更高级别的功能(讨论一些想法,如添加
asyncio.spawn
asyncio.create_任务

我还可以指出,在我看来,使用能够处理任何
可等待的
的通用函数非常方便,而不仅仅是协同程序

然而,Guido的答案很明确:“当从协同程序创建任务时,应该使用适当命名的
循环。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替换为
await long\u operation())
,以确保将来(long\u operation())
可以感受到差异。

对于您的示例,这三种类型都是异步执行的。唯一的区别是,在第三个示例中,您预先生成了所有10个协程,并一起提交给循环。所以只有最后一个随机给出输出

注意:仅对Python 3.7有效(对于Python 3.5,请参阅)

从官方文件:

(在Python3.7中添加)是生成新任务而不是生成新任务的首选方法


详情: 现在,在Python 3.7以后的版本中,有两个顶级包装函数(类似但不同):

  • :直接呼叫。()
  • 如果它是协程,或者只是为了确保返回类型为a,那么它也会调用。(). 无论如何,
    Task
    仍然是
    的未来
    ,因为它的类继承()

嗯,通常这两个包装函数都会帮助您调用。唯一的区别是
确保未来
接受任何对象并帮助您将其转换为未来。您还可以在
确保未来
中提供自己的
事件循环
参数。根据您是否需要这些功能,您可以简单地选择要使用的包装器。

根据Guido的说法,如果您确实需要任务对象,您应该使用
create\u task
,这通常是不需要的:@bj0感谢您的帮助