Python 为什么运行异步协程不能恢复控制?

Python 为什么运行异步协程不能恢复控制?,python,python-3.x,asynchronous,python-asyncio,Python,Python 3.x,Asynchronous,Python Asyncio,我有一个示例代码: 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 d

我有一个示例代码:

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()
这段代码期望两个函数并行运行。我的意思是两者的产出应该同时出现。但事实并非如此。原因是我自己实现了一个sleep函数
asynchsleep
。如果我使用
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()
我还查找了
asyncio.sleep
函数的签名:

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

asyncio.sleep
函数有什么是我实现的
asyncio.sleep
函数没有的?它们都是协程,为什么它们的行为不同呢?

当你做异步的事情时,你没有连续的流程。有一个,在它们之间有一个and池:当当前任务等待时,循环将控制传递给池中的一个其他任务

,正如@user2357112在注释中优雅地指出的那样,它是同步的,它只是在一段时间内阻止执行,而没有提供继续执行其他协同程序的机会

那么,
asyncio.sleep
有什么,而您的
asyncio.sleep
没有什么:

  • 它创建一个新对象(表示尚未完成的任务的结果的特殊对象)
  • 新任务不执行任何操作,但需要指定的时间
  • 因此,新的未来将在时机成熟时产生
    结果
  • 该任务有助于阻止等待
    asyncio.sleep
    的流,但不会阻止其他任务

感受差异。

当你做异步的事情时,你没有连续的流程。有一个,在它们之间有一个and池:当当前任务等待时,循环将控制传递给池中的一个其他任务

,正如@user2357112在注释中优雅地指出的那样,它是同步的,它只是在一段时间内阻止执行,而没有提供继续执行其他协同程序的机会

那么,
asyncio.sleep
有什么,而您的
asyncio.sleep
没有什么:

  • 它创建一个新对象(表示尚未完成的任务的结果的特殊对象)
  • 新任务不执行任何操作,但需要指定的时间
  • 因此,新的未来将在时机成熟时产生
    结果
  • 该任务有助于阻止等待
    asyncio.sleep
    的流,但不会阻止其他任务

感受差异。

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


asyncio循环正在运行,计划执行一个和两个操作。循环选择运行dou_one,因为您不会屈服或等待代码返回到循环,直到函数完成

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


asyncio循环正在运行,计划执行一个和两个操作。循环选择运行dou_one,因为您不会屈服或等待代码返回到循环,直到函数完成

时间。睡眠是同步的。如果
time.sleep
像那样工作,
asyncio.sleep
不存在。@user2357112不是
asyncio
将同步包装为异步的原因吗?在异步函数中插入同步调用并不能使其异步。@dirn:
time.sleep
不受CPU限制。@TechJS从技术上讲,每个函数调用都是阻塞的(它会阻止调用线程,直到函数返回或引发),但在这种情况下,像
list.append
这样的函数在很短的时间内完成它们的工作,而
time.sleep
sock.recv
这样的函数可以无限期地阻塞线程。解决方案是不调用此类函数,而是使用它们的异步变量。这就是asyncio所做的,使用s当协同路由等待的条件(例如asyncio.sleep)出现时,使用一些额外的魔法来暂停协同路由还没有准备好。
time.sleep
是同步的。如果
time.sleep
像这样工作,
asyncio.sleep
就不存在了。@user2357112不是
asyncio
将同步包装成异步的原因吗?在异步函数中插入同步调用不会使其异步。@dirn:
time.sleep
不是“t CPU绑定。@TechJS从技术上讲,每个函数调用都是阻塞的(它会阻塞调用线程,直到函数返回或引发),但在这种情况下,像
list.append
这样的函数在很短的时间内完成它们的工作,而
time.sleep
sock.recv
这样的函数可以无限期地阻塞线程。解决方案是不调用此类函数,而是使用它们的异步变量。这就是asyncio所做的,使用s当协程所等待的条件(如asyncio.sleep)尚未就绪时,可以使用一些额外的魔法来暂停协程。