Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.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 协同程序的收益与任务的收益_Python_Python 3.x_Asynchronous_Concurrency_Python Asyncio - Fatal编程技术网

Python 协同程序的收益与任务的收益

Python 协同程序的收益与任务的收益,python,python-3.x,asynchronous,concurrency,python-asyncio,Python,Python 3.x,Asynchronous,Concurrency,Python Asyncio,Guido van Rossum在2014年关于郁金香/Asyncio的演讲中: 任务与合作计划的对比 比较: res=某个合作项目的收益率(…) res=任务的收益率(某些协同程序(…) 任务可以在不等待的情况下取得进展 在你等待其他东西的时候记日志 i、 e.来自 我完全没有抓住要点 在我看来,两种结构都是相同的: 在裸协同路由的情况下-它得到调度,因此无论如何都会创建任务,因为调度器与任务一起运行,所以协同路由调用方协同路由将被挂起,直到被调用方完成,然后可以自由地继续执行

Guido van Rossum在2014年关于郁金香/Asyncio的演讲中:

任务与合作计划的对比

  • 比较:

    • res=某个合作项目的收益率(…)
    • res=任务的收益率(某些协同程序(…)
  • 任务可以在不等待的情况下取得进展

    • 在你等待其他东西的时候记日志
      • i、 e.来自
我完全没有抓住要点

在我看来,两种结构都是相同的:

在裸协同路由的情况下-它得到调度,因此无论如何都会创建任务,因为调度器与任务一起运行,所以协同路由调用方协同路由将被挂起,直到被调用方完成,然后可以自由地继续执行

任务
的情况下,仍然会安排新任务,调用方协同路由等待其完成

<> P>在这两种情况下代码执行的方式有什么不同,开发者在实践中应该考虑哪些影响?

p、 s.

非常感谢权威来源(GvR、PEP、文档、核心开发人员注释)的链接。

对于调用方的共同例程,
coroutine()的收益感觉就像一个函数调用(即,当coroutine()完成时,它将再次获得控制权)

yield from Task(coroutine())
另一方面,感觉更像是创建一个新线程
Task()
几乎立即返回,并且很可能在
coroutine()
完成之前调用方获得了控制权


f()
th=threading.Thread(target=f,args=())之间的差异;th.start();join()是显而易见的,对吗?

使用
asyncio.Task(coro())
的意义在于,您不想显式地等待
coro
,但希望在等待其他任务时在后台执行
coro
。这就是Guido幻灯片的意思

[A]
任务
可以在不等待的情况下取得进展…只要等待 为了别的什么

考虑这个例子:

import asyncio

@asyncio.coroutine
def test1():
    print("in test1")


@asyncio.coroutine
def dummy():
    yield from asyncio.sleep(1)
    print("dummy ran")


@asyncio.coroutine
def main():
    test1()
    yield from dummy()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:

dummy ran
in test1
dummy ran
正如您所看到的,
test1
从未实际执行过,因为我们没有显式地对它调用
yield from

现在,如果我们使用
asyncio.async
围绕
test1
包装一个
Task
实例,结果是不同的:

import asyncio

@asyncio.coroutine
def test1():
    print("in test1")


@asyncio.coroutine
def dummy():
    yield from asyncio.sleep(1)
    print("dummy ran")


@asyncio.coroutine
def main():
    asyncio.async(test1())
    yield from dummy()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:

dummy ran
in test1
dummy ran
因此,使用
yield from asyncio.async(coro())
,实际上没有实际的理由,因为它比
yield from coro()
慢,没有任何好处;它引入了将
coro
添加到内部
asyncio
调度程序的开销,但这不是必需的,因为使用
yield from
可以保证
coro
无论如何都会执行。如果您只想调用一个协程并等待它完成,只需直接从
协程中退出即可

旁注:

我正在使用
asyncio.async
*而不是直接使用
Task

不要直接创建
Task
实例:使用
async()
函数或
BaseEventLoop.create_task()
方法


*请注意,从Python 3.4.4开始,
asyncio.async
被弃用,取而代之的是。

如PEP 380中所述,引入yield from的公认PEP文档,表达式
res=yield from f()
来自以下循环的思想:

for res in f():
    yield res
这样,事情变得非常清楚:如果
f()
some\u coroutine()
,则执行coroutine。另一方面,如果
f()
some\u coroutine()
不会执行,只有新创建的生成器作为第一个参数传递给
任务。\uuuuu init\uuuu

结论:

  • res=yield from some_coroutine()
    =>coroutine继续执行并返回下一个值
  • res=yield from Task(some\u coroutine())
    =>创建一个新任务,该任务存储一个未执行的
    some\u coroutine()
    生成器对象

asyncio中根本没有优先级。对于裸协同路由,您必须使用
yield from coro()
来运行协同路由,在任务构造的情况下,如
async(coro())
将与其他并行执行协同路由。是的,您是对的。从技术上讲,
yield from coro()
立即执行协同程序,
async(coro())
通过
循环调度执行。call_soon()
call。好吧,这是实现细节。Trollius不使用
yield from
且与asyncio不完全兼容。与asyncio完全兼容的自定义事件循环利用
yield from
并重用调用
loop.call_soon()
的asyncio.Task。非100%兼容的系统可能会邀请自己的合同,并有自己的实施细节。是的,如果PyPy支持3.4(目前仅支持3.2),它将以与CPython 3.4相同的方式与协同程序一起工作。至少我这么认为,但不能保证。我是CPython核心开发人员,不是PyPy。