【问题标题】:Waiting for output from a subprocess which does not terminate等待来自未终止的子进程的输出
【发布时间】:2013-12-10 04:17:19
【问题描述】:

我需要从我的脚本中运行一个子进程。子进程是一个交互式(类似 shell)应用程序,我通过子进程'stdin 向它发出命令。
在我发出命令后,子进程将结果输出到stdout,然后等待下一个命令(但不会终止)。

例如:

from subprocess import Popen, PIPE
p = Popen(args = [...], stdin = PIPE, stdout = PIPE, stderr = PIPE, shell = False)
# Issue a command:
p.stdin.write('command\n')
# *** HERE: get the result from p.stdout ***
# CONTINUE with the rest of the script once there is not more data in p.stdout
# NOTE that the subprocess is still running and waiting for the next command
# through stdin.

我的问题是从p.stdout 获取结果。脚本需要在p.stdout中有新数据时获取输出;但是一旦没有更多数据,我想继续执行脚本。
子进程没有终止,所以我不能使用communicate()(它等待进程终止)。
发出命令后,我尝试从p.stdout 读取,如下所示:

res = p.stdout.read()

但是子进程不够快,我得到的结果是空的。
我想过循环轮询p.stdout,直到我得到一些东西,但是我怎么知道我得到了一切?无论如何,这似乎很浪费。

有什么建议吗?

【问题讨论】:

  • 尝试使用异步库/框架,例如电路(例如:bitbucket.org/circuits/circuits-dev/src/tip/examples/ping.py
  • @JamesMills,异步可能可行,但我认为这会使我想做的事情过于复杂。如果没有其他解决方案出现,我会这样做。谢谢。
  • 唯一的其他方法是使用线程来隐藏阻塞调用。任何其他选项都将涉及某种并发/异步库/框架。你也可以使用一个:)

标签: python subprocess


【解决方案1】:

在 gevent-1.0 中使用 gevent.subprocess 替换标准的 subprocess 模块。它可以使用同步逻辑执行并发任务,并且不会阻塞脚本。这里有一个关于gevent.subprocess的简短教程

【讨论】:

  • 我的问题不在于并发性和同步性。我已经澄清了这个问题。谢谢。
【解决方案2】:

circuits-dev 中使用circuits.io.Process 来包装对子进程的异步调用。

示例:https://bitbucket.org/circuits/circuits-dev/src/tip/examples/ping.py

【讨论】:

  • 感谢 James,但问题不在于并发性和同步性。我已经澄清了这个问题。
  • 我认为这个问题不一定有一个“简单”的答案。
【解决方案3】:

在研究了几个选项后,我得出了两个解决方案:

  1. 使用fcntl 模块将子进程的标准输出流设置为非阻塞。
  2. 使用线程将子进程的输出收集到代理队列,然后从主线程读取队列。

我在this post 中描述了这两种解决方案(以及问题及其根源)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 2020-09-09
    • 2021-09-08
    • 2013-11-08
    • 2020-08-30
    • 2021-11-07
    • 1970-01-01
    相关资源
    最近更新 更多