Обработка сообщений от дочернего процесса тщательно stderr и stdout с Python - PullRequest
6 голосов
/ 26 января 2011

Мой код на python порождает дочерний процесс и выводит сообщения как stdout, так и stderr.Мне нужно распечатать их по-другому.

У меня есть следующий код для порождения дочернего процесса и получения результата stdout из него.

cmd = ["vsmake.exe", "-f"]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, ''):
    print line,
    sys.stdout.flush()
    pass
p.wait()

Как я могу изменить код, чтобы проверить, выводит ли дочерний процесс сообщение также через stderr?

ДОБАВЛЕНО

Мне нужно распечатать stderr и stdout, как только дочерний процесс что-то распечатает.И это кроссплатформенная реализация, поэтому она должна работать на Mac / Linux / PC.

Ответы [ 2 ]

7 голосов
/ 26 января 2011
p = Popen(cmd, bufsize=1024,
stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
p.stdin.close()
print p.stdout.read() #This will print the standard output from the spawned process
print p.stderr.read() #This is what you need, error output <-----

Таким образом, в основном вывод ошибок перенаправляется на stderr Pipe.

Если вам нужно что-то большее в реальном времени. Я имею в виду, что строки печатаются, как только порожденный процесс печатает что-то в stdout or stderr`, тогда вы можете сделать что-то вроде:

def print_pipe(type_pipe,pipe):
    for line in iter(pipe.readline, ''):
         print "[%s] %s"%(type_pipe,line),

p = Popen(cmd, bufsize=1024,
stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)

t1 = Thread(target=print_pipe, args=("stdout",p.stdout,))
t1.start()
t2 = Thread(target=print_pipe, args=("stderr",p.stderr,))
t2.start()

#optionally you can join the threads to wait till p is done. This is avoidable but it 
# really depends on the application.
t1.join()
t2.join()

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

1 голос
/ 26 января 2011

Самый простой способ сделать это независимо от платформы - использовать потоки (к сожалению).Вот пример кода:

def redirect_to_stdout(stream):
    for line in stream:
        sys.stdout.write(line)
        sys.stdout.flush()

cmd = ["vsmake.exe", "-f"]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr_thread = threading.Thread(target=redirect_to_stdout, args=(p.stderr,))
stderr_thread.start()
redirect_to_stdout(p.stdout)
p.wait()
stderr_thread.join()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...