从子进程实时捕获stdout

2024-04-29 20:11:26 发布

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

我想在Windows中subprocess.Popen()rsync.exe,并用Python打印stdout。

我的代码可以工作,但在文件传输完成之前,它不会捕获进度!我想实时打印每个文件的进度。

现在使用Python3.1,因为我听说它应该更擅长处理IO。

import subprocess, time, os, sys

cmd = "rsync.exe -vaz -P source/ dest/"
p, line = True, 'start'


p = subprocess.Popen(cmd,
                     shell=True,
                     bufsize=64,
                     stdin=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     stdout=subprocess.PIPE)

for line in p.stdout:
    print(">>> " + str(line.rstrip()))
    p.stdout.flush()

Tags: 文件代码ioimportcmdtruetimewindows
3条回答

我知道这是个老话题,但现在有了解决办法。使用选项--outbuf=L调用rsync。示例:

cmd=['rsync', '-arzv','--backup','--outbuf=L','source/','dest']
p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, b''):
    print '>>> {}'.format(line.rstrip())

关于subprocess的一些经验法则。

  • 从不使用shell=True。它不必要地调用额外的shell进程来调用您的程序。
  • 调用进程时,参数作为列表传递。^python中的{}是一个列表,C中的argv也是这样。因此,您将列表传递给Popen以调用子进程,而不是字符串。
  • 不要在不阅读时将stderr重定向到PIPE
  • 当你不写的时候,不要重定向stdin

示例:

import subprocess, time, os, sys
cmd = ["rsync.exe", "-vaz", "-P", "source/" ,"dest/"]

p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)

for line in iter(p.stdout.readline, b''):
    print(">>> " + line.rstrip())

也就是说,当rsync检测到它连接到管道而不是终端时,它很可能会缓冲它的输出。这是默认行为-当连接到管道时,程序必须显式刷新stdout以获得实时结果,否则标准C库将缓冲。

要进行测试,请尝试运行以下命令:

cmd = [sys.executable, 'test_out.py']

并创建一个包含以下内容的test_out.py文件:

import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")

执行该子流程时,应该给出“Hello”,并在给出“World”之前等待10秒。如果这发生在上面的python代码上,而不是rsync,那就意味着rsync本身正在缓冲输出,所以您运气不好。

一种解决方案是使用类似pexpect的方法直接连接到pty

在Linux上,我也遇到了同样的问题,即去掉缓冲区。我最后使用了“stdbuf-o0”(或者,unbuffer from expect)来消除管道缓冲。

proc = Popen(['stdbuf', '-o0'] + cmd, stdout=PIPE, stderr=PIPE)
stdout = proc.stdout

然后我可以在stdout上使用select.select。

另见https://unix.stackexchange.com/questions/25372/

相关问题 更多 >