19

我想使用管道在从 python 脚本启动的独立应用程序中执行多个命令。我可以可靠地将命令传递给程序的标准输入的唯一方法是使用 Popen.communicate 但它会在命令执行后关闭程序。如果我使用 Popen.stdin.write 比命令只执行 5 次左右的 1 次,它就不能可靠地工作。我究竟做错了什么?

详细说明一下:

我有一个应用程序,它监听标准输入的命令并逐行执行它们。我希望能够运行应用程序并将各种命令传递给它,基于用户与 GUI 的交互。这是一个简单的测试示例:

import os, string
from subprocess import Popen, PIPE

command = "anApplication" 
process = Popen(command, shell=False, stderr=None, stdin=PIPE)

process.stdin.write("doSomething1\n")
process.stdin.flush()
process.stdin.write("doSomething2\n")
process.stdin.flush()

我希望看到这两个命令的结果,但我没有得到任何回应。(如果我多次执行 Popen.write 行之一,它偶尔会起作用。)

如果我执行:

process.communicate("doSomething1")

它运行良好,但应用程序终止。

4

4 回答 4

1

如果我正确理解您的问题,您希望与控制台应用程序进行交互(即发送命令并阅读响应)。

如果是这样,您可能需要检查类似 Expect 的库,例如 Python 的 pexpect:http: //pexpect.sourceforge.net

它会让你的生活更轻松,因为它会处理同步问题,ddaa 也描述了这个问题。另见: http ://www.noah.org/wiki/Pexpect#Q:_Why_not_just_use_a_pipe_.28popen.28.29.29.3F

于 2011-09-30T18:20:39.883 回答
0

您在问题中的代码应该按原样工作。如果不是,那么您的实际代码不同(例如,您可能使用stdout=PIPE它可能会改变子缓冲行为)或者它可能表明子应用程序本身存在错误,例如Python 2 中的预读错误,即您的输入由父进程正确发送,但它卡在子进程的内部输入缓冲区中。

以下适用于我的 Ubuntu 机器:

#!/usr/bin/env python
import time
from subprocess import Popen, PIPE

LINE_BUFFERED = 1

#NOTE: the first argument is a list
p = Popen(['cat'], bufsize=LINE_BUFFERED, stdin=PIPE,
          universal_newlines=True)
with p.stdin:
    for cmd in ["doSomething1\n", "doSomethingElse\n"]:
        time.sleep(1) # a delay to see that the commands appear one by one
        p.stdin.write(cmd)
        p.stdin.flush() # use explicit flush() to workaround
                        #   buffering bugs on some Python versions
rc = p.wait()
于 2011-09-24T08:48:36.257 回答
0

这里真正的问题是应用程序是否正在缓冲它的输出,以及是否有任何事情可以阻止它。大概当用户生成命令并单击 GUI 上的按钮时,您希望在要求用户输入下一个命令之前查看该命令的输出。

不幸的是,您无法在客户端执行任何操作subprocess.Popen来确保当您向应用程序传递命令时,应用程序会确保所有输出都刷新到最终目的地。你可以随心所欲地调用flush(),但如果它不这样做,并且你无法做到,那么你注定要寻找解决方法。

于 2011-12-14T10:10:39.840 回答
-1

听起来您的应用程序正在以一种奇怪的方式处理来自管道的输入。这意味着在您关闭管道之前,它不会收到您发送的所有命令。

所以我建议的方法就是这样做:

process.stdin.write("command1\n")
process.stdin.write("command2\n")
process.stdin.write("command3\n")
process.stdin.close()

听起来您的 Python 程序并没有从应用程序读取输出,所以如果您像这样一次发送所有命令并不重要。

于 2010-01-29T15:52:51.513 回答