本文介绍了同步调用协程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下以下非常常见的情况:您已经编写了一个又长又复杂的函数,并且意识到一些代码应该提取到单独的函数中以便重用和/或可读性。通常,此额外的函数调用不会更改程序的语义。

但是,现在假设您的函数是一个协程,并且您要提取的代码包含至少一个异步调用。现在,将其提取到单独的函数中会突然更改您的程序语义,方法是插入一个新的点,在该点上协同例程产生,事件循环进行控制,并且可以在两者之间调度任何其他协同例程。

前面示例:

async def complicated_func():
    foo()
    bar()
    await baz()

以下示例:

async def complicated_func():
    foo()
    await extracted_func()

async def extracted_func():
    bar()
    await baz()

在上面的示例中,保证了complicated_func在调用foo()和调用bar()之间不会挂起。重构后,此保证将丢失。

我的问题是:是否可以调用extracted_func(),使其立即执行,就好像它的代码是内联的一样?或者,是否有其他方法可以在不更改程序语义的情况下执行此类常见的重构任务?

推荐答案

实际上不是。

已经是这样了。

await some_coroutine()意味着some_coroutine可能会将控制权交还给事件循环,但它不会这样做,直到它真正等待将来(例如某些I/O操作)。

考虑此示例:

import asyncio

async def coro():
    print(1)
    await asyncio.sleep(0)
    print(3)

async def main():
    loop.call_soon(print, 2)
    await coro()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

请注意2如何按照预期在13之间打印。

这也意味着可以通过编写以下代码冻结事件循环:

async def coro():
    return

async def main():
    while True:
        await coro()

在这种情况下,事件循环永远没有机会运行其他任务。

这篇关于同步调用协程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 08:04