在协同链接期间,await如何将控制权交还给事件循环?

Gau*_*ani 8 python python-3.x async-await python-asyncio

我正在尝试使用Python 3.6中的asyncio,并且很难弄清楚为什么这段代码的行为方式如此.

示例代码:

import asyncio

async def compute_sum(x, y):
    print("Compute %s + %s ..." % (x, y))
    await asyncio.sleep(5)
    print("Returning sum")
    return x + y

async def compute_product(x, y):
    print("Compute %s x %s ..." % (x, y))
    print("Returning product")
    return x * y

async def print_computation(x, y):
    result_sum = await compute_sum(x, y)
    result_product = await compute_product(x, y)
    print("%s + %s = %s" % (x, y, result_sum))
    print("%s * %s = %s" % (x, y, result_product))

loop = asyncio.get_event_loop()
loop.run_until_complete(print_computation(1, 2))
Run Code Online (Sandbox Code Playgroud)

输出:

Compute 1 + 2 ...
Returning sum
Compute 1 x 2 ...
Returning product
1 + 2 = 3
1 * 2 = 2
Run Code Online (Sandbox Code Playgroud)

预期产出:

Compute 1 + 2 ...
Compute 1 x 2 ...
Returning product
Returning sum
1 + 2 = 3
1 * 2 = 2
Run Code Online (Sandbox Code Playgroud)

我对预期产量的推理:

虽然compute_sum协程在compute_product协程之前被正确调用,但我的理解是,一旦我们命中await asyncio.sleep(5),控件将被传递回事件循环,这将开始执行compute_product协程.为什么在我们点击compute_product协程中的print语句之前执行"返还总和"?

aba*_*ert 10

关于协程如何工作你是对的; 你的问题在于你如何称呼他们.特别是:

result_sum = await compute_sum(x, y)
Run Code Online (Sandbox Code Playgroud)

这会调用协程compute_sum ,然后等待直到完成.

所以,compute_sum确实屈服于调度程序await asyncio.sleep(5),但没有其他人醒来.你的print_computationcoro已经在等待了compute_sum.甚至compute_product还没有人开始,所以它肯定无法运行.

如果你想要启动多个协同程序并让它们同时运行,不要await每个协同程序; 你需要一起等待他们中的很多人.例如:

async def print_computation(x, y):
    awaitable_sum = compute_sum(x, y)
    awaitable_product = compute_product(x, y)        
    result_sum, result_product = await asyncio.gather(awaitable_sum, awaitable_product)
    print("%s + %s = %s" % (x, y, result_sum))
    print("%s * %s = %s" % (x, y, result_product))
Run Code Online (Sandbox Code Playgroud)

(无论awaitable_sum是裸露的协程,Future对象还是其他可以await编辑的东西都无关紧要; gather无论哪种方式都可以.)

或者,也许更简单:

async def print_computation(x, y):
    result_sum, result_product = await asyncio.gather(
        compute_sum(x, y), compute_product(x, y))
    print("%s + %s = %s" % (x, y, result_sum))
    print("%s * %s = %s" % (x, y, result_product))
Run Code Online (Sandbox Code Playgroud)

请参阅示例部分中的并行执行任务.