我想在使用管道从python脚本启动的独立应用程序中执行多个命令。我能够可靠地将命令传递给程序的stdin的唯一方法是使用Popen.communicate,但它会在命令执行后关闭程序。如果我使用Popen.stdin.write而不是命令只执行5次左右,那么它就不可靠。我做错了什么?
详细说明一下:
我有一个应用程序,它监听stdin的命令并逐行执行它们。 我希望能够运行应用程序并根据用户与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")
它完美无缺,但应用程序终止。
答案 0 :(得分:1)
如果我正确理解您的问题,您希望与控制台应用程序进行交互(即发送命令并阅读响应)。
如果是这样,您可能需要检查类似Expect的库,例如pexpect for Python:http://pexpect.sourceforge.net
它将使您的生活更轻松,因为它将照顾同步,ddaa也描述的问题。也可以看看: http://www.noah.org/wiki/Pexpect#Q:_Why_not_just_use_a_pipe_.28popen.28.29.29.3F
答案 1 :(得分:0)
问题中的代码应该按原样运行。如果它没有那么你的实际代码是不同的(例如,你可能使用stdout=PIPE
that may change the child buffering behavior)或者它可能表明子应用程序本身存在一个错误,例如the read-ahead bug in 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()
答案 2 :(得分:0)
这里真正的问题是应用程序是否正在缓冲其输出,以及是否有任何东西可以阻止它。据推测,当用户生成命令并单击GUI上的按钮时,您希望在需要用户输入下一个命令之前查看该命令的输出。
不幸的是,您无法在subprocess.Popen
的客户端执行任何操作,以确保在您向应用程序传递命令时,应用程序确保将所有输出刷新到最终目标。您可以随心所欲地调用flush()
,但如果它不能做同样的事情,而您无法做到,那么您注定要寻找解决方法。
答案 3 :(得分:-1)
听起来您的应用程序正在以奇怪的方式处理来自管道的输入。这意味着在关闭管道之前,它不会获取您发送的所有命令。
所以我建议的方法就是这样做:
process.stdin.write("command1\n")
process.stdin.write("command2\n")
process.stdin.write("command3\n")
process.stdin.close()
听起来你的Python程序不是从应用程序读取输出,所以如果你像这样一次发送命令就没关系。