Как я могу получить выходные данные дочернего процесса, порожденного конвейерным процессом? - PullRequest
0 голосов
/ 24 мая 2018

Я хочу постоянно отслеживать процесс по конвейеру и печатать его stdout и stderr по мере его поступления (мне не интересно получать весь вывод сразу после его выхода).Проблема состоит в том, что переданный по конвейеру процесс порождает другой дочерний процесс, и stdout и stderr этого порожденного процесса не доступны, используя каналы исходного процесса.

А именно, я хочу запустить pythonзапрограммируйте таким образом, так что конвейерный процесс является интерпретатором python, но интерпретатор python порождает выполнение программы python в другом подпроцессе, поэтому я не могу получить вывод этого (фактический вывод программы).Если при запуске программы произошла ошибка, я могу получить ее, потому что она напечатана на оригинальном интерпретаторе Python stderr.Но нормальное stdout из самой программы потеряно для меня.

Я использую subprocess.Popen.

Редактировать: комментатор попросил образец кода, я не думаю, что этомногое добавляет, но вот мой код (PopenProcess - это интеллектуальный класс-обертка для subrpocess.Popen, но ничего особенного не делает):

class BTask:
    def __init__(self, name, cmds, color = "NONE"):
        self.name = name
        self.cmds = cmds
        self.color = color
        self.proc = None

    def procreadline(self, sline):
        print(ANSI[self.color] + self.name + ANSI["ENDC"] + " > " + ANSI[self.color] + sline)

    def procreaderror(self, sline):
        print(ANSI[self.color] + self.name + ANSI["BRIGHTWHITE"] + " ! " + ANSI["BRIGHTRED"] + sline)

    def run(self):        
        print(ANSI["GREEN"])
        print("running task: {} {}".format(ANSI["BRIGHTGREEN"], self.name))
        pargs = []
        if len(self.cmds) > 1:
            pargs = self.cmds[1:]        
        print(ANSI[self.color])
        self.proc = PopenProcess(
            self.cmds[0],
            self.procreadline,
            read_error_callback = self.procreaderror,
            proc_args = pargs,
            ignore_cwd = True
            )

    def kill(self):
        print(ANSI["RED"])
        print("killing task: {} {}".format(ANSI["BRIGHTRED"], self.name))
        self.proc.kill()

    def is_alive():
        return self.proc.is_alive()

1 Ответ

0 голосов
/ 24 мая 2018

В качестве конвейерного процесса вместо

subprocess.Popen(['python', 'myprog.py'])

следует использовать

subprocess.Popen(['python', '-u', 'myprog.py'])

Тогда это работает.

Проблема была с буферизованным выводом, и -u переключатель отключает это (разрешает небуферизованный вывод).

...