остановить Popen, когда строка встречается в терминальном выпуске [duplicate]

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

6 ответов

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

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

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

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

136
ответ дан Rômulo C 24 August 2018 в 06:31
поделиться

Немного опоздал на вечеринку, но был удивлен, не увидев, что я считаю самым простым решением здесь:

import io
import subprocess

proc = subprocess.Popen(["prog", "arg"], stdout=subprocess.PIPE)
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):  # or another encoding
    # do something with line
22
ответ дан jbg 24 August 2018 в 06:31
поделиться

Следующая версия ответа Rômulo работает для меня на Python 2 и 3 (2.7.12 и 3.6.1):

import os
import subprocess

process = subprocess.Popen(command, stdout=subprocess.PIPE)
while True:
  line = process.stdout.readline()
  if line != b'':
    os.write(1, line)
  else:
    break
1
ответ дан mdh 24 August 2018 в 06:31
поделиться

Вы хотите передать эти дополнительные параметры в subprocess.Popen:

bufsize=1, universal_newlines=True

Затем вы можете выполнять итерацию, как в вашем примере. (Протестировано с помощью Python 3.5)

10
ответ дан nikoliazekter 24 August 2018 в 06:31
поделиться

Я попробовал это с python3, и он работал, source

def output_reader(proc):
    for line in iter(proc.stdout.readline, b''):
        print('got line: {0}'.format(line.decode('utf-8')), end='')


def main():
    proc = subprocess.Popen(['python', 'fake_utility.py'],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)

    t = threading.Thread(target=output_reader, args=(proc,))
    t.start()

    try:
        time.sleep(0.2)
        import time
        i = 0

        while True:
        print (hex(i)*512)
        i += 1
        time.sleep(0.5)
    finally:
        proc.terminate()
        try:
            proc.wait(timeout=0.2)
            print('== subprocess exited with rc =', proc.returncode)
        except subprocess.TimeoutExpired:
            print('subprocess did not terminate in time')
    t.join()
0
ответ дан shakram02 24 August 2018 в 06:31
поделиться

Действительно, если вы отсортировали итератор, тогда буферизация теперь может быть вашей проблемой. Вы можете сказать python в подпроцессе, чтобы не буферировать его вывод.

proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)

становится

proc = subprocess.Popen(['python','-u', 'fake_utility.py'],stdout=subprocess.PIPE)

Мне это нужно, когда вы вызываете python из python.

16
ответ дан Steve Carter 24 August 2018 в 06:31
поделиться
Другие вопросы по тегам:

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