从需要stdin的子进程实时打印stdout

时间:2013-07-01 19:14:04

标签: python subprocess

这是this question的后续内容,但如果我想将参数传递给stdinsubprocess,我该如何实时获得输出?这就是我现在拥有的;我还尝试用Popen模块中的call替换subprocess,这只会导致脚本挂起。

from subprocess import Popen, PIPE, STDOUT
cmd = 'rsync --rsh=ssh -rv --files-from=- thisdir/ servername:folder/'
p = Popen(cmd.split(), stdout=PIPE, stdin=PIPE, stderr=STDOUT)
subfolders = '\n'.join(['subfolder1','subfolder2'])
output = p.communicate(input=subfolders)[0]
print output

在前一个我无需通过stdin的问题中,我被建议使用p.stdout.readline,那里没有空间将任何内容传递给stdin

附录:这适用于转移,但我只在结尾处看到输出,我希望在转移过程中看到转移的详细信息。

3 个答案:

答案 0 :(得分:30)

为了实时从子进程中获取stdout,你需要准确地确定你想要的行为;具体来说,您需要决定是要逐行还是逐个字符地处理输出,以及是否要在等待输出时阻塞或在等待时能够执行其他操作。

看起来你的情况可能足以以行缓冲的方式读取输出,阻塞直到每个完整的行进入,这意味着subprocess提供的便利功能足够好:

p = subprocess.Popen(some_cmd, stdout=subprocess.PIPE)
# Grab stdout line by line as it becomes available.  This will loop until 
# p terminates.
while p.poll() is None:
    l = p.stdout.readline() # This blocks until it receives a newline.
    print l
# When the subprocess terminates there might be unconsumed output 
# that still needs to be processed.
print p.stdout.read()

如果您需要写入流程的标准输入,只需使用另一个管道:

p = subprocess.Popen(some_cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
# Send input to p.
p.stdin.write("some input\n")
p.stdin.flush()
# Now start grabbing output.
while p.poll() is None:
    l = p.stdout.readline()
    print l
print p.stdout.read()

Pace 另一个答案是,没有必要通过文件间接传递输入到子进程。

答案 1 :(得分:3)

像我这样的事情

from subprocess import Popen, PIPE, STDOUT

p = Popen('c:/python26/python printingTest.py', stdout = PIPE, 
        stderr = PIPE)
for line in iter(p.stdout.readline, ''):
    print line
p.stdout.close()

使用迭代器将基本上返回实时结果..

为了向stdin发送输入,你需要像

这样的东西
other_input = "some extra input stuff"
with open("to_input.txt","w") as f:
   f.write(other_input)
p = Popen('c:/python26/python printingTest.py < some_input_redirection_thing', 
         stdin = open("to_input.txt"),
         stdout = PIPE, 
         stderr = PIPE)

这类似于

的linux shell命令
%prompt%> some_file.o < cat to_input.txt

请参阅alps回答,以便更好地传递给stdin

答案 2 :(得分:2)

如果在开始读取输出之前传递所有输入,并且如果通过“实时”传递,则表示子进程刷新其stdout缓冲区时:

from subprocess import Popen, PIPE, STDOUT

cmd = 'rsync --rsh=ssh -rv --files-from=- thisdir/ servername:folder/'
p = Popen(cmd.split(), stdout=PIPE, stdin=PIPE, stderr=STDOUT, bufsize=1)
subfolders = '\n'.join(['subfolder1','subfolder2'])
p.stdin.write(subfolders)
p.stdin.close() # eof
for line in iter(p.stdout.readline, ''):
    print line, # do something with the output here
p.stdout.close()
rc = p.wait()