代码之家  ›  专栏  ›  技术社区  ›  H.Harry

为什么wait不等待asyncio。创建\u subprocess\u exec()

  •  4
  • H.Harry  · 技术社区  · 8 年前

    我正在编写一个基于教程的协同程序,以在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!
    

    当我尝试删除进程时。等待():

    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')
    
    • 那么为什么wait不等待asyncio呢。创建_subprocess_exec()?

    文档( https://docs.python.org/3/library/asyncio-task.html#coroutine )表示:

    结果=等待未来或结果=未来收益 暂停 在未来完成之前,协同路由将返回未来结果,或引发异常,该异常将被传播。(如果取消future,将引发CancelledError异常。)请注意,任务是未来,关于未来的所有说法也适用于任务。

    结果=等待协同方案或结果=协同方案的收益 等待 让另一个协同例程生成结果(或引发异常,异常将被传播)。协同路由表达式必须是对另一个协同路由的调用。

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

    raise exception–使用wait或yield from在等待此异常的协同程序中引发异常。

    • 协同路由时,流程的实际流程是什么 正在挂起 等待 ?

    下面是asyncio的源代码。创建\u subprocess\u 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()
    
    1 回复  |  直到 6 年前
        1
  •  11
  •   user2357112    8 年前

    您等待进程开始。你没有等它结束。 await process.wait() 等待它完成。