Python 为什么等待不';t wait asyncio.create_subprocess_exec()

Python 为什么等待不';t wait asyncio.create_subprocess_exec(),python,asynchronous,python-asyncio,coroutine,Python,Asynchronous,Python Asyncio,Coroutine,我正在编写一个基于教程的协同程序,以在python中执行shell命令。以下是基本的: import asyncio async def async_procedure(): process = await asyncio.create_subprocess_exec('ping', '-c', '2', 'google.com') await process.wait() print('async procedure done.') loop = asyncio.g

我正在编写一个基于教程的协同程序,以在python中执行shell命令。以下是基本的:

import asyncio

async def async_procedure():
    process = await asyncio.create_subprocess_exec('ping', '-c', '2', 'google.com')
    await process.wait()
    print('async procedure done.')

loop = asyncio.get_event_loop()
loop.run_until_complete(async_procedure())
loop.close()
上面的代码工作得很好。结果如下:

PING google.com (...) 56(84) bytes of data.
64 bytes from ...: icmp_seq=1 ttl=46 time=34.8 ms
64 bytes from ...: icmp_seq=2 ttl=46 time=34.5 ms

--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 33.771/34.437/34.881/0.407 ms
Process done!
尝试删除进程时。请稍候()

脚本无法按预期工作:

Process done! # This line should be lastest line
PING google.com (...) 56(84) bytes of data.
64 bytes from ...: icmp_seq=1 ttl=46 time=21.1 ms
64 bytes from ...: icmp_seq=2 ttl=46 time=21.8 ms

--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 21.135/21.469/21.803/0.334 ms
但在一个非常类似的例子中没有问题:

async def async_procedure():
    await asyncio.sleep(2)
    print('async procedure done')
  • 那么为什么wait不等待asyncio.create_subprocess_exec()
文件()说:

result=wait future或result=yield from future–暂停协程,直到将来完成,然后返回未来的结果,或引发将被传播的异常。(如果未来被取消,它将引发CanceledError异常。)请注意,任务就是未来,关于未来的所有说法也适用于任务

result=wait coroutine或result=yield from coroutine–等待另一个coroutine生成结果(或引发异常,该异常将被传播)。协程表达式必须是对另一个协程的调用

返回表达式–使用wait或yield from向正在等待此结果的协同程序生成结果

raiseexception–使用wait或yield from在协程中引发等待此异常的异常

  • 当协同路由挂起等待时,进程的实际流程是什么
下面是asyncio.create_subprocess_exec()和asyncio.sleep()的源代码。它们都是协同程序:

@coroutine
def create_subprocess_exec(program, *args, stdin=None, stdout=None,
                           stderr=None, loop=None,
                           limit=streams._DEFAULT_LIMIT, **kwds):
    if loop is None:
        loop = events.get_event_loop()
    protocol_factory = lambda: SubprocessStreamProtocol(limit=limit,
                                                        loop=loop)
    transport, protocol = yield from loop.subprocess_exec(
                                            protocol_factory,
                                            program, *args,
                                            stdin=stdin, stdout=stdout,
                                            stderr=stderr, **kwds)
    return Process(transport, protocol, loop)


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

您等待流程开始。你没有等它结束<代码>等待进程。等待()等待它完成。

我不敢相信这个问题这么简单。谢谢@user2357112!
@coroutine
def create_subprocess_exec(program, *args, stdin=None, stdout=None,
                           stderr=None, loop=None,
                           limit=streams._DEFAULT_LIMIT, **kwds):
    if loop is None:
        loop = events.get_event_loop()
    protocol_factory = lambda: SubprocessStreamProtocol(limit=limit,
                                                        loop=loop)
    transport, protocol = yield from loop.subprocess_exec(
                                            protocol_factory,
                                            program, *args,
                                            stdin=stdin, stdout=stdout,
                                            stderr=stderr, **kwds)
    return Process(transport, protocol, loop)


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