使用Popen.stdin执行多个命令

2024-03-28 08:16:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我想使用管道在从python脚本启动的独立应用程序中执行多个命令。我能可靠地将命令传递给程序的stdin的唯一方法是使用Popen.communicate,但它会在命令执行后关闭程序。如果我使用Popen.stdin.write,那么该命令执行的次数大约为5次中的1次,那么它就不可靠。我做错什么了?

详细说明一下:

我有一个应用程序,它监听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")

它工作得很好,但应用程序终止。


Tags: import命令程序脚本应用程序管道stdinprocess
3条回答

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

不幸的是,在subprocess.Popen的客户端上,您无法确保在传递应用程序命令时,应用程序确保所有输出都刷新到最终目标。你可以随心所欲地调用flush(),但如果它做不到这一点,而你做不到,那么你注定要寻找解决办法。

你的代码应该能正常工作。如果没有,那么实际的代码可能不同(例如,您可能使用^{} 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()

如果我正确理解您的问题,您需要与控制台应用程序交互(即发送命令和读取响应)。

如果是这样,您可能需要检查一个Expect-like库,比如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

相关问题 更多 >