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

hat*_*rix 21 python subprocess

这是一个跟进这个问题,但如果我想传递一个参数stdinsubprocess,我怎么能得到实时输出?这就是我现在拥有的; 我也尝试从模块替换Popen,这只会导致脚本挂起.callsubprocess

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
Run Code Online (Sandbox Code Playgroud)

在前一个我没有通过的问题stdin我被建议使用p.stdout.readline,那里没有任何空间来管道stdin.

附录:这适用于转移,但我只看到输出的结尾,我希望看到转移的细节发生时.

Alp*_*Alp 34

为了实时从子进程中获取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()
Run Code Online (Sandbox Code Playgroud)

如果需要写入进程的stdin,只需使用另一个管道:

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()
Run Code Online (Sandbox Code Playgroud)

吴佩慈对方的回答,没有必要通过间接以文件通过输入到子进程.

  • 当不带参数调用 `read()` 时,在遇到 `EOF` 之前不会返回(它试图读取它被调用的整个文件对象,并且它不知道它已经消耗了所有文件,直到它到达`EOF`)。在阅读输入时,这很少是人们想要的行为。您应该将指定数量的字节作为参数传递给 `read()`(在这种情况下,`read()` 调用将在遇到该字节数或 `EOF` 后返回,以先到者为准)或使用 `readline( )`(遇到换行符后会返回)。 (2认同)
  • 如果子进程在 stderr 上生成足够的输出,您的代码将死锁。不要使用 `stderr=PIPE`,除非你稍后阅读 `p.stderr`。 (2认同)