1

我正在编写一个脚本,其中外部系统命令有时可能需要用户输入。我无法正确处理。我曾尝试使用 os.popen4 和 subprocess 模块,但无法实现所需的行为。

下面提到的示例将使用“cp”命令显示此问题。(“cp”命令用于显示此问题,我正在调用一些不同的 exe,在某些情况下可能会类似地提示用户响应)。在此示例中,磁盘上存在两个文件,当用户尝试将 file1 复制到 file2 时,会出现一条conformer 消息。

proc = subprocess.Popen("cp -i a.txt b.txt", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,)
stdout_val, stderr_val = proc.communicate()
print stdout_val

b.txt?

proc.communicate("y")

现在在这个例子中,如果我只读取 stdout/stderr 并打印它,稍后如果我尝试根据用户的输入写入“y”或“n”,我会收到一个错误,即通道已关闭。

有人可以帮我在python中实现这种行为,这样我就可以先打印标准输出,然后再接受用户输入并稍后再写标准输入。

我在 python 中的 subprocess.PIPE 上的非阻塞读取中找到了另一个解决方案(线程),不确定它是否有帮助。但它似乎是来自 cp 命令的打印问题,我已经修改了代码,但不确定如何编写线程代码。

import sys
from subprocess import PIPE, Popen
from threading import Thread
try:
    from Queue import Queue, Empty
except ImportError:
    from queue import Queue, Empty

ON_POSIX = 'posix' in sys.builtin_module_names

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()

 p = Popen(['cp', '-i', 'a.txt', 'b.txt'],stdin=PIPE, stdout=PIPE, bufsize=1, close_fds=ON_POSIX)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.start()

try:
    line = q.get_nowait()
except Empty:
    print('no output yet')
else:
   pass
4

2 回答 2

1

Popen.communicate将运行子流程以完成,因此您不能多次调用它。您可以直接使用stdinandstdout属性,尽管这样做有风险,因为如果进程使用块缓冲或缓冲区已满,您可能会死锁:

stdout_val = proc.stdout.readline()
print stdout_val
proc.stdin.write('y\n')

由于存在死锁的风险,并且如果进程使用块缓冲,这可能不起作用,您最好考虑使用pexpect

于 2012-07-23T13:15:21.657 回答
0

我对这个问题没有技术答案。更多只是一个解决方案。它与进程等待输入的方式有关,一旦你与进程通信,一个 None 输入就足以关闭进程。

对于您的cp示例,您可以做的是立即使用proc.poll(). 如果返回值为None,您可能会认为它正在尝试等待输入并可以向您的用户提问。然后,您可以通过 将响应传递给进程proc.communicate(response)。然后它将传递该值并继续该过程。

也许其他人可以用一个更技术性的原因来解释为什么初始communicate值为 None 会关闭该过程。

于 2012-07-23T05:32:22.160 回答