来自同步(标准)函数的 asyncio 运行

asyncio running from a synchronous (standard) function

阅读了文档并观看了一些视频后,我正在测试 asyncio 作为 threading 的替代方案。

文档在这里: https://docs.python.org/3/library/asyncio.html

我构建了以下代码,期望它会产生以下结果。

before the sleep
hello
world

但实际上是产生这个(world 出现在 hello 之前):

before the sleep
world
hello

代码如下:

import asyncio
import time


def main():
    ''' main entry point for the program '''
    # create the event loop and add to the loop
    # or run directly.

    asyncio.run(main_async())
    return

async def main_async():
    ''' the main async function '''
    await foo()
    await bar()
    return

async def foo():
    print('before the sleep')
    await asyncio.sleep(2)
    # time.sleep(0)
    print('world')
    return

async def bar():
    print('hello')
    await asyncio.sleep(0)
    return



if __name__=='__main__':
    ''' This is executed when run from the command line '''
    main()

main() 函数调用异步 main_async() 函数,后者又调用 foobar 异步函数,而这两个 运行 await asyncio.sleep(x)命令。

所以我的问题是:为什么 hello world 以错误的(意外的)顺序出现,因为我期望 world 大约被打印 hello 后 2 秒?

await 立即编辑了 foo(),因此 bar() 从未安排到 foo() 已 运行 完成;在 await 完成之前,main_async 的执行永远不会在 和 await 之后执行 事情。如果你想同时安排它们并让它们交错,替换:

await foo()
await bar()

类似的东西:

await asyncio.gather(foo(), bar())

这会将两个可等待对象转换为任务,在 运行ning 异步事件循环中安排它们,然后等待两个任务 运行 完成。两者同时安排,当一个块在 await(和 await 块上时,因为只有 await 将控制权交还给事件循环),另一个将被允许 运行(当现在 运行ning 任务 await 或完成时,控制只能 return 到另一个任务)。 =30=]

基本上,您必须记住 asyncio合作 多任务处理。如果您只执行一项任务,并且该任务执行 await,则没有其他可安排的任务,因此在 await 完成之前没有其他 运行s。如果您通过 await 以外的任何方式进行阻止,您仍然会保持事件循环,即使它已准备就绪,也没有其他任何机会进入 运行。因此,要从 asyncio 中获得任何好处,您需要注意:

  1. 确保在原始任务阻塞 await 时及时启动其他任务以占用事件循环。
  2. 确保你只通过 await 阻塞,这样你就不会不必要地独占事件循环。