代码之家  ›  专栏  ›  技术社区  ›  Amir Hossein Baghernezad

为什么运行异步协同程序不返回控制?

  •  0
  • Amir Hossein Baghernezad  · 技术社区  · 6 年前

    我有一个示例代码:

    import asyncio
    
    import time
    
    async def asyncsleep(number):
        time.sleep(number)
    
    async def do_one():
        await asyncsleep(1)
        print("one 1")
        await asyncsleep(1)
        print("one 2")
        await asyncsleep(1)
        print("one 3")
    
    async def do_two():
        await asyncsleep(1)
        print("two 1")
        await asyncsleep(1)
        print("two 2")
        await asyncsleep(1)
        print("two 3")
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([
        do_one(),
        do_two()
    ]))
    loop.close()
    

    此代码期望两个函数并行运行。我的意思是两者的输出应该同时进行。但事实并非如此。原因是我自己实现了一个睡眠功能 asyncsleep . 如果我使用 asyncio.sleep 不是这样,一切都很好。

    import asyncio
    
    import time
    
    async def asyncsleep(number):
        time.sleep(number)
    
    async def do_one():
        await asyncio.sleep(1)
        print("one 1")
        await asyncio.sleep(1)
        print("one 2")
        await asyncio.sleep(1)
        print("one 3")
    
    async def do_two():
        await asyncio.sleep(1)
        print("two 1")
        await asyncio.sleep(1)
        print("two 2")
        await asyncio.sleep(1)
        print("two 3")
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([
        do_one(),
        do_two()
    ]))
    loop.close()
    

    我也查过 异步睡眠 功能:

    @coroutine
    def sleep(delay, result=None, *, loop=None):
        """Coroutine that completes after a given time (in seconds)."""
        if delay == 0:
            yield
            return result
    
        if loop is None:
            loop = events.get_event_loop()
        future = loop.create_future()
        h = future._loop.call_later(delay,
                                    futures._set_result_unless_cancelled,
                                    future, result)
        try:
            return (yield from future)
        finally:
            h.cancel()
    

    什么 异步睡眠 函数已实现 异步睡眠 函数没有?他们都是共济会成员,为什么他们的行为不同?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Konstantin Sekeresh    6 年前

    当你做异步的事情时,你没有连续的流动。有一个 event loop ,有一个水池 tasks 并在它们之间切换:当当前任务 await s,循环将控制权传递给池中的另一个任务。

    time.sleep 正如@user2357112在注释中优雅地指出的那样,它是同步的,它只会阻止执行一段时间,而不会给继续执行不同协同工作的机会。

    所以,什么 asyncio.sleep 拥有和你 asyncsleep 没有:

    • 它创造了一个新的 Future (表示任务结果的特殊对象 然而 完成)
    • 那项新任务什么也不做,但需要一定的时间
    • 所以新的未来将产生 result 时间到了
    • 该任务有助于阻止 异步睡眠 已等待,但不会阻止其他任务。

    感受差异。

        2
  •  2
  •   MarkReedZ    6 年前

    异步不是线程。异步代码在遇到等待或函数完成之前不会放弃控制。你的睡眠功能不会放弃控制,所以:

    Asyncio循环正在运行,并且计划了do-one和do-two。循环选择运行do_one,因为不生成或等待代码,所以在函数完成之前不会返回循环。