считайте подпроцесс stdout линию за линией

Если у вас есть данный ключ, вы можете использовать метод higherKey(key) и lowerKey(key), соответственно.

Есть также соответствующие xxxEntry() варианты.

216
задан deft_code 29 December 2014 в 06:19
поделиться

2 ответа

Прошло много времени с тех пор, как я последний раз работал с Python, но я думаю, что проблема заключается в операторе for line в proc.stdout, который считывает весь вход перед итерацией по нему. Решением является использование readline() вместо этого:

#filters output
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
while True:
  line = proc.stdout.readline()
  if not line:
    break
  #the real code does filtering here
  print "test:", line.rstrip()

Конечно, вам все равно придется иметь дело с буферизацией подпроцесса.

Примечание: согласно документации решение с итератором должно быть эквивалентно использованию readline(), за исключением буфера для чтения вперед, но (или именно из-за этого) предложенное изменение дало мне другие результаты (Python 2.5 на Windows XP).

168
ответ дан 23 November 2019 в 04:19
поделиться

Функция, позволяющая выполнять итерации по stdout и stderr одновременно, в режиме реального времени, построчно

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

Функция использует очереди для объединения обоих каналов Popen в один итератор.

Здесь мы создаем функцию read_popen_pipes():

from queue import Queue, Empty
from concurrent.futures import ThreadPoolExecutor


def enqueue_output(file, queue):
    for line in iter(file.readline, ''):
        queue.put(line)
    file.close()


def read_popen_pipes(p):

    with ThreadPoolExecutor(2) as pool:
        q_stdout, q_stderr = Queue(), Queue()

        pool.submit(enqueue_output, p.stdout, q_stdout)
        pool.submit(enqueue_output, p.stderr, q_stderr)

        while True:
            out_line = err_line = ''

            try:
                out_line = q_stdout.get_nowait()
                err_line = q_stderr.get_nowait()
            except Empty:
                pass

            yield (out_line, err_line)

            if p.poll() is not None:
                break

read_popen_pipes() и используем:

import subprocess as sp


with sp.Popen(my_cmd, stdout=sp.PIPE, stderr=sp.PIPE, text=True) as p:

    for out_line, err_line in read_popen_pipes(p):

        # Do stuff with each line, e.g.:
        print(out_line, end='')
        print(err_line, end='')

    return p.poll() # return status-code
0
ответ дан 23 November 2019 в 04:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: