在Python中实时更新可执行子流程控制台输出

时间:2019-04-04 22:01:44

标签: python-3.x console-application executable

我一直在阅读this questionand this one,并指出那里提出的解决方案没有达到我要尝试的目的。这个想法类似于this question,但在这里我给出一个更好的例子。

我需要在Python 3.7中构建一个GUI,以监视和控制用C编写的旧软件的执行。现在,我试图简单地从Python调用测试可执行文件并将其打印在GUI上,但是现在就可以在与python相同的控制台上打印了。问题在于,可执行文件要花很长时间才能完全执行,但同时会打印控制台消息,我需要我的GUI及时读取这些消息。

这是一个有效的示例:

在Python 3.7中:

import sys
from threading import Thread
import time
import subprocess

class HandleTarget(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        subprocess.Popen(["hello.exe"], stdout=sys.stdout, bufsize=1)

class Printer(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        for i in range(1, 15):
            sys.stdout.write("Hi back ("+str(i)+")!\n")
            time.sleep(1.0)

thread_1 = HandleTarget()
thread_2 = Printer()

# Launching threads:
thread_1.start()
thread_2.start()

现在,示例可执行文件(“ hello.exe”)可以像这样在C中构建:

#include <stdio.h>
#include <time.h>

int main() {
    struct timespec time;
    double tic = 0;
    double toc = 0;

    for( int ii = 0; ii < 3 ; ii++){
        clock_gettime(CLOCK_MONOTONIC, &time);
        tic = time.tv_sec;
        toc = tic;

        while(toc-tic<3) {
        clock_gettime(CLOCK_MONOTONIC, &time);
        toc    = time.tv_sec;
        }
        printf("Hello #%d \n",ii);
    }
    return(0); 
}

理想情况下,我需要干预消息“ Hello”和“ Hi back”。但是,如果我运行上面的python脚本,则会得到:

Hi back (1)!
Hi back (2)!
Hi back (3)!
Hi back (4)!
Hi back (5)!
Hi back (6)!
Hi back (7)!
Hi back (8)!
Hi back (9)!
Hello #0 
Hello #1 
Hello #2 
Hi back (10)!
Hi back (11)!
Hi back (12)!
Hi back (13)!
Hi back (14)!

显然,可执行文件的输出仅在执行完成时打印。这意味着,如果旧版可执行文件正在运行,则只有完成后才会显示任何内容。

编辑:我对此没有严格的实时限制,如果打印实际上需要几分钟,那很好,问题是,如果一个流程需要运行几天,那么每隔几天小时(最好是几分钟),需要使用可执行文件中的控制台打印来更新GUI。

1 个答案:

答案 0 :(得分:4)

考虑阅读Popen.stdout

https://docs.python.org/3/library/subprocess.html?highlight=subprocess#subprocess.Popen.stdout

这是更新程序的输出:

$ python test.py
Hi back (1)!
Hi back (2)!
Hi back (3)!
Hello #0
Hi back (4)!
Hi back (5)!
Hi back (6)!
Hello #1
Hi back (7)!
Hi back (8)!
Hi back (9)!
Hello #2
Hi back (10)!
Hi back (11)!
Hi back (12)!
Hi back (13)!
Hi back (14)!

更新的程序:

import sys
from threading import Thread
import time
import subprocess

class HandleTarget(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        proc = subprocess.Popen(["hello.exe"], stdout=subprocess.PIPE)
        for line in proc.stdout:
            print(line.strip().decode('utf-8'))


class Printer(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        for i in range(1, 15):
            sys.stdout.write("Hi back ("+str(i)+")!\n")
            time.sleep(1.0)

thread_1 = HandleTarget()
thread_2 = Printer()

# Launching threads:
thread_1.start()
thread_2.start()

编辑:

我还修改了C程序以在打印后刷新stdout,缓冲的stdout似乎是问题的根本原因:

    printf("Hello #%d \n",ii);
    fflush(stdout);