使用 subprocess.Popen() 从 python 脚本实时输出 [英] Realtime output from python script using subprocess.Popen()

查看:134
本文介绍了使用 subprocess.Popen() 从 python 脚本实时输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

After searching around, I defined a function to execute command like in terminal:

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)

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

It works fine(output is realtime), when i

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

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

However, when i use execute_cmd to run a python script, the output will print out until the process is done.

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= 参数似乎不起作用.

Sorry for not explaining why 'catch the stdout and then write it to stdout again'. Here i really want to do is catching script outputs to logger, the logger output them to screen(StreamHandler) and log file(FileHandler). I builded and tested the logger part, now the 'execute' part. And ignore the stdout= parameter seems not work.

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

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

Because of step 2, if i ignore stdout= parameter, the outputs of scripts will still output to STDOUT, and will not log in file.

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

Maybe i can set stdout= to logger?

推荐答案

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

This is a common problem of the underlying output system, notably on Linux or other Unix-like systems. The io library is smart enough to flush output on each \n when it detects that output is directed to a terminal. But this automatic flush does not occur when output is redirected to a file or a pipe, probably for performance reasons. It is not really a problem when only the data matters, but it leads to weird behaviour when timing matters too.

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

Unfortunately I know no simple way to fix it from the caller program(*). The only possibility is to have the callee force flushing on each line/block or to use unbuffered output:

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

import time
import sys

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

<小时>

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

这篇关于使用 subprocess.Popen() 从 python 脚本实时输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆