Why await doesn't wait asyncio.create

I'm writing a coroutine to execute shell command in python base on a tutorial. Here are basic:

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

This code above work perfectly. It gives a result like that:

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!

When I try remove process.wait():

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

The script doesn't work as expected:

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

But there is no problem in a very similar example:

async def async_procedure():
    await asyncio.sleep(2)
    print('async procedure done')
  • So why await doesn't wait asyncio.create_subprocess_exec() ?
  • The docs (https://docs.python.org/3/library/asyncio-task.html#coroutine) says:

    result = await future or result = yield from future – suspends the coroutine until the future is done, then returns the future's result, or raises an exception, which will be propagated. (If the future is cancelled, it will raise a CancelledError exception.) Note that tasks are futures, and everything said about futures also applies to tasks.

    result = await coroutine or result = yield from coroutine – wait for another coroutine to produce a result (or raise an exception, which will be propagated). The coroutine expression must be a call to another coroutine.

    return expression – produce a result to the coroutine that is waiting for this one using await or yield from.

    raise exception – raise an exception in the coroutine that is waiting for this one using await or yield from.

  • What is actually process's flow when coroutine suspending and waiting ?
  • Here are source code of asyncio.create_subprocess_exec() and asyncio.sleep() are coroutine. Both of them are coroutines:

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

    You waited for the process to start. You did not wait for it to finish. await process.wait() waits for it to finish.

    链接地址: http://www.djcxy.com/p/53248.html

    上一篇: Async是否等待关键字等同于ContinueWith lambda?

    下一篇: 为什么等待不等asyncio.create