首页 文章

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

提问于
浏览
5

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

Example code:

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))

Output:

Compute 1 + 2 ...
Returning sum
Compute 1 x 2 ...
Returning product
1 + 2 = 3
1 * 2 = 2

Expected Output:

Compute 1 + 2 ...
Compute 1 x 2 ...
Returning product
Returning sum
1 + 2 = 3
1 * 2 = 2

My reasoning for expected output:

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

2 回答

  • -1

    你're right about how the coroutines work; your problem is in how you'重新打电话给他们 . 特别是:

    result_sum = await compute_sum(x, y)
    

    这会调用协程 compute_sum 然后等待它完成 .

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

    如果你想要启动多个协同程序并让它们同时运行,请不要 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))
    

    (无论 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))
    

    请参阅示例部分中的Parallel execution of tasks .

  • 7

    这是它的工作原理 . 让我们使用主线程作为主要参考...

    主线程处理来自不同位置的事件和工作 . 如果从其他线程一次触发3个事件,则主线程一次只能处理一个事件 . 如果主线程正在处理你的循环,它将继续处理它,直到返回方法(或函数),然后再处理其他工作 .

    这意味着“其他工作”被放置在队列中以在主线程上运行 .

    当您使用'async await'时,您可以编写'async'来让它知道该方法将(或可以)分解为它自己的队列集 . 然后,当你说“等待”它应该在另一个线程上工作 . 当它执行时,允许主线程处理存储在队列中的其他事件和工作,而不是仅仅在那里等待 .

    因此,当await工作完成时,它也将方法的剩余部分放在主线程的队列中 .

    所以在这些方法中它按顺序没有't continue processing but places the remaining work in a queue to be accomplished when the await is complete. Therefore it' . await compute_sum(x, y) 将控制权交还给主线程以进行其他工作,当它完成时,其余部分将被添加到要处理的队列中 . 所以 await compute_product(x, y) 在前者完成后排队 .

相关问题