当前位置: 首页 > 面试题库 >

从子进程实时捕获标准输出

柯子琪
2023-03-14
问题内容

我想subprocess.Popen()在Windows中使用rsync.exe,并在Python中打印标准输出。

我的代码可以运行,但是直到文件传输完成后才能捕获进度!我想实时打印每个文件的进度。

既然我听说使用Python 3.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()

问题答案:

一些经验法则subprocess

  • 永远不要使用shell=True。它不必要地调用额外的shell进程来调用您的程序。
  • 调用进程时,参数作为列表传递。sys.argv在python中是一个列表,argv在C中也是如此。因此,您将* * 列表传递给Popen来调用子流程,而不是字符串。
  • 不阅读时不要重定向stderr到a 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”,并等待10秒钟后才能给出“ World”。如果上述情况发生在上面的python代码上,而不是发生rsync,则意味着rsync它本身正在缓冲输出,因此您很不走运。

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



 类似资料:
  • 问题内容: 我试图用Python编写程序,并被告知运行.exe文件。运行此.exe文件时,它会吐出大量数据,并且我需要在屏幕上打印出一定的行。我很确定我需要使用或类似的东西,但是我是子处理的新手,没有任何线索。有人有简单的方法让我完成此工作吗? 问题答案: 像这样:

  • 问题内容: 在客户端计算机上遇到网络问题时,我希望能够运行一些命令行并将其结果通过电子邮件发送给我自己。 我发现Runtime.exec将允许我执行任意命令,但是将结果收集到String中会更有趣。 我意识到我可以将输出重定向到文件,然后从文件中读取,但是我的幻想是告诉我,有一种更优雅的方法。 有什么建议吗? 问题答案: 你需要在此过程中同时捕获标准输出和标准错误。然后,你可以将std写出到文件/

  • 问题内容: 我了解到,在Python中执行命令时,应该使用子进程。我想要实现的是通过ffmpeg对文件进行编码,并观察程序输出,直到文件完成。Ffmpeg将进度记录到stderr。 如果我尝试这样的事情: 调用child.communicate()后,程序无法继续执行,并等待命令完成。还有其他方法可以跟踪输出吗? 问题答案: communication()阻塞直到子进程返回,所以循环中的其余各行仅

  • 问题内容: 在Linux 3.0 / C ++下: 我想要一个执行以下操作的函数: 显然上述方法不起作用,但是您可以理解。我有一个字符串s,我希望将其作为应用程序“ foo”的子进程执行的标准输入传递,然后将其标准输出记录到字符串r中,然后将其返回。 我应该使用linux syscall或posix函数的什么组合? 问题答案: eerpini提供的代码无法正常工作。请注意,例如,之后将使用在父级中

  • 问题内容: 我想运行一个系统进程,拦截输出,并在Python脚本中逐行实时地对其进行修改。 我的最佳尝试是等待过程完成后再打印,它是: 该脚本仅每半秒打印一行: 是否有一个简单的解决方案可以实时迭代输出?我必须使用线程吗? 从前,我用Perl编写脚本,这真是小菜一碟: 问题答案: 遍历文件不可避免地将大量内容缓冲-这是所有Python 2. *实现的一个已知问题。它可以按照您在Python 3.1

  • 问题内容: 说我有一个下面的函数,如何捕获Process.spawn调用的输出?如果花费的时间超过指定的超时时间,我也应该能够终止该过程。 请注意,该功能还必须是跨平台的(Windows / Linux)。 谢谢。 问题答案: 您可以使用并告诉使用重定向的输出,而无需外部gem。 当然,仅从Ruby 1.9.2开始(我个人建议1.9.3) 以下是Spinach BDD在内部用于捕获输出和err输出