Python 3.x 同步调用协同程序

Python 3.x 同步调用协同程序,python-3.x,python-asyncio,Python 3.x,Python Asyncio,想象一下以下非常常见的情况:您编写了一个长而复杂的函数,并且意识到一些代码应该提取到一个单独的函数中,以便重用和/或可读性。通常,这个额外的函数调用不会改变程序的语义 但是,现在假设您的函数是一个协程,并且您要提取的代码至少包含一个异步调用。将它提取到一个单独的函数中,现在通过插入一个新的点突然改变了您的程序语义,在这个点上,协程产生,事件循环获得控制,并且任何其他协程都可以在其间进行调度 之前的示例: async def complicated_func(): foo() ba

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

但是,现在假设您的函数是一个协程,并且您要提取的代码至少包含一个异步调用。将它提取到一个单独的函数中,现在通过插入一个新的点突然改变了您的程序语义,在这个点上,协程产生,事件循环获得控制,并且任何其他协程都可以在其间进行调度

之前的示例:

async def complicated_func():
    foo()
    bar()
    await baz()
示例如下:

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

async def extracted_func():
    bar()
    await baz()
在前面的示例中,保证在调用
foo()
和调用
bar()
之间不会挂起
复杂函数。重构之后,这种保证就失去了

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

重构之后,这种保证就失去了

实际上不是

是否可以调用extracted_func(),使其立即执行,就像其代码是内联的一样

情况已经是这样了

await some\u coroutine()
意味着
some\u 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
是如何按照预期在
1
3
之间打印的

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

async def coro():
    return

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

在这种情况下,事件循环永远不会有机会运行另一个任务。

我不认为我完全理解。我的印象是,调用
wait some_coroutine()
会隐式地创建一个未来(或一个任务),将其排队到事件循环,并让位于事件循环,以便它可以自行调用下一个可用的任务。现在,你是说事实并非如此,而是立即调用
某个_coroutine()
,而不涉及事件循环?没错,如果你在等待可以等待的东西,比如@Vincent提到的i/o操作、线程/进程执行器、超时,eventloop可以控制(asyncio.sleep)…更多关于“wait”的信息并不能神奇地使函数成为异步或非阻塞的。@MaxTet
现在,你是说事实并非如此,而是说某个_corroutine()立即调用,而不涉及事件循环?
这正是发生的情况。您在评论的第一部分中描述的是
等待asyncio。确保未来(coro())
。好的,谢谢您澄清这一点。看来,我的假设是完全错误的。是否有文档来源来支持这一点?