簡體   English   中英

為什么等待不等待asyncio.create_subprocess_exec()

[英]Why await doesn't wait asyncio.create_subprocess_exec()

我正在根據教程編寫協程以在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.wait()時:

async def async_procedure():
    await asyncio.create_subprocess_exec('ping', '-c', '2', 'google.com')
    print('async procedure 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')
  • 那么,為什么不等待asyncio.create_subprocess_exec()呢?

docs( https://docs.python.org/3/library/asyncio-task.html#coroutine )說:

結果=等待未來或結果=來自未來的收益– 暫停協程直到完成未來,然后返回未來的結果,或引發異常,該異常將被傳播。 (如果取消了future,則會引發CancelledError異常。)請注意,任務就是future,有關future的所有說明也適用於任務。

結果=等待協程或結果=從協程產生– 等待另一個協程產生結果(或引發異常,該異常將被傳播)。 協程表達式必須是對另一個協程的調用。

return expression –使用await或yield from將結果生成到等待此協程的協程。

引發異常-在協程中使用await或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()

您等待該過程開始。 您沒有等待它完成。 await process.wait()等待它完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM