在Python中使用子流程模块编写stdin之前如何打印stdout

在Python中使用子流程模块编写stdin之前如何打印stdout,python,subprocess,Python,Subprocess,我正在编写一个脚本,在这个脚本中,外部系统命令有时可能需要用户输入。我无法妥善处理这件事。我尝试过使用os.popen4和子流程模块,但未能实现所需的行为 下面提到的示例将使用“cp”命令显示此问题。(“cp”命令用于显示此问题,我正在调用一些不同的exe,在某些情况下可能会类似地提示用户响应)。在本例中,磁盘上有两个文件,当用户试图将文件1复制到文件2时,会出现一条符合者消息 proc = subprocess.Popen("cp -i a.txt b.txt", shell=True, st

我正在编写一个脚本,在这个脚本中,外部系统命令有时可能需要用户输入。我无法妥善处理这件事。我尝试过使用os.popen4和子流程模块,但未能实现所需的行为

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

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

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

有人能帮我在python中实现这个行为吗?这样我就可以先打印stdout,然后再接受用户输入并编写stdin

我从中找到了另一个解决方案(线程),不确定是否有帮助。但它似乎是打印来自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

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

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


也许其他人可以插话提出一个更技术性的原因,说明为什么初始值为“无”的
通信
会结束这个过程。

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

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


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

Popen.communicate
会运行子进程直到完成,所以不能多次调用它。您可以直接使用,但这是有风险的,因为如果进程使用块缓冲或缓冲区已满,则可能会死锁:

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

因为存在死锁的风险,因为如果进程使用块缓冲,这可能不起作用,那么您最好考虑使用Addio.

< P> <代码> Popen。通信< /代码>将运行子进程完成,因此不能多次调用它。您可以直接使用,但这是有风险的,因为如果进程使用块缓冲或缓冲区已满,则可能会死锁:

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

因为存在死锁的风险,因为如果进程使用块缓冲,那么这可能不起作用,您最好考虑使用Addio.

。您是否希望允许用户向管道转发响应,或者只是让它说“Y”?不管怎样,我希望自己解释用户响应,然后代码本身应该与管道通信。因此,用户可以键入“y”或“n”或其他任何内容。如果问题发生在子线程方面,线程代码将不会有帮助,即,主线程不会阻塞,但队列中不会看到任何输出。按照@ecatmur的建议尝试。你的孩子是什么?你能改变它的缓冲设置吗?Child exe是IBM cleartool,我想我不能改变它的缓冲。我将尝试winpexpect等。您希望允许用户将响应转发到管道,还是让它无论如何都显示“y”?我希望自己解释用户响应,然后代码本身应该与管道通信。因此,用户可以键入“y”或“n”或其他任何内容。如果问题发生在子线程方面,线程代码将不会有帮助,即,主线程不会阻塞,但队列中不会看到任何输出。按照@ecatmur的建议尝试。你的孩子是什么?你能改变它的缓冲设置吗?Child exe是IBM cleartool,我想我不能改变它的缓冲。我将尝试winpexpect等。我尝试了这段代码,但它在执行proc.stdout.readline()@sarbjit时挂起了。是的,它可能使用了块缓冲。尝试使用pexpect.pexpect在windows上不起作用。我希望我的代码可以在windows和linux上移植。
wexpect
是pexpect的windows端口:我尝试了这段代码,但在执行proc.stdout.readline()@sarbjit时它挂起了是的,它可能使用了块缓冲。尝试使用pexpect.pexpect在windows上不起作用。我希望我的代码可以在windows和linux上移植。
wexpect
是pexpect的windows端口: