【问题标题】:Realtime output from python script using subprocess.Popen()使用 subprocess.Popen() 从 python 脚本实时输出
【发布时间】:2018-05-17 07:54:44
【问题描述】:

搜索后,我定义了一个函数来执行终端中的命令:

import shlex
import subprocess
def execute_cmd(cmd):
    p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    for line in iter(p.stdout.readline, b''):  # b'' here for python3
        sys.stdout.write(line.decode(sys.stdout.encoding))

    error = p.stderr.read().decode()
    if error:
        raise Exception(error)

它工作正常(输出是实时的),当我

execute_cmd('ping -c 5 www.google.com')

但是,当我使用execute_cmd 运行 python 脚本时,输出将打印出来,直到该过程完成。

execute_cmd('python test.py')

脚本:test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time

print('hello')
time.sleep(2)
print('hello, again')

我该如何解决?谢谢!


很抱歉没有解释为什么“捕获标准输出,然后再次将其写入标准输出”。在这里我真正想做的是将脚本输出捕获到记录器,记录器将它们输出到屏幕(StreamHandler)和日志文件(FileHandler)。我构建并测试了记录器部分,现在是“执行”部分。并且忽略stdout= 参数似乎不起作用。

管道:

  1. 设置记录器;
  2. 将 STDOUT、STDERR 重定向到记录器;
  3. 执行脚本;

由于第2步,如果我忽略stdout=参数,脚本的输出仍然会输出到STDOUT,并且不会登录文件。

也许我可以将stdout= 设置为记录器?

【问题讨论】:

  • 为什么抓到stdout,然后又写到stdout?您可以忽略该参数。
  • @Sraw 抱歉没有解释,我真正想做的是将脚本输出捕获到记录器,记录器将它们输出到屏幕(StreamHandler)和日志文件(FileHandler)。我构建并测试了记录器,现在是“执行”部分。并且忽略stdout=参数将不起作用。

标签: python subprocess


【解决方案1】:

这是底层输出系统的常见问题,尤其是在 Linux 或其他类 Unix 系统上。 io 库足够智能,可以在检测到输出定向到终端时刷新每个 \n 上的输出。但是当输出被重定向到文件或管道时,这种自动刷新不会发生,可能是出于性能原因。当只有数据很重要时,这并不是一个真正的问题,但是当时间也很重要时,它会导致奇怪的行为。

不幸的是,我不知道从调用程序 (*) 中修复它的简单方法。唯一的可能性是让被调用者在每行/块上强制刷新或使用无缓冲输出:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import sys

print('hello')
sys.stdout.flush()
time.sleep(2)
print('hello, again')

(*) 防弹方法是使用伪终端。调用者控制主端并将客户端传递给被调用者。该库将检测终端并在每一行上自动刷新。但它在 Unix 世界之外不再是可移植的,也不是真正的简单方式。

【讨论】:

  • 问题背后的原因比解决方案更重要,谢谢你给我看兔子洞。
猜你喜欢
  • 1970-01-01
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-16
  • 2014-01-15
  • 2021-08-30
  • 1970-01-01
相关资源
最近更新 更多