Python связывается с подпроцессом - PullRequest
2 голосов
/ 06 сентября 2011

У меня есть подпроцесс, который постоянно генерирует данные, но большая часть данных мне не интересна. Однако иногда, в случайные моменты времени, мне нужно взять образец вывода - дело в том, что мне нужно его прочитатьна четко определенных границах.Например, предположим, что процесс выдает постоянные 100 байтов в секунду, а полезная информация состоит из кусков по 100 байтов.После того, как он был запущен в течение 4 секунд, я прошу посмотреть 100 байтов вывода, тогда меня будут интересовать байты 400-499 включительно.Но если я спрашиваю в 4,1 секунды, я не хочу перехватывать и получать байты 410-509, мне нужно подождать и посмотреть байты 500-599.В противном случае процесс должен счастливо передавать свой вывод на /dev/null и . Я не хочу когда-либо блокировать поток вывода .Мой друг Фред может также попросить 100 байтов, скажем, за 4,6 секунды, поэтому мне также нужно отключить этот материал и сделать данные доступными для чтения несколькими потребителями.

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

Ответы [ 3 ]

2 голосов
/ 06 сентября 2011

Что ж, я новичок в python, но кажется, что proc.communicate или proc.stdout.readline / readlines ждут, пока процесс не завершится.

Насколько мне известно, вы можете реализовать ротационное ведение журнала и перенаправить вывод в файл, затем с помощью подпроцесса вы можете запустить tailf -n XX logfile в цикле до завершения программы и печатать вывод всякий раз, когда есть запрос со стороны пользователя.

1 голос
/ 06 сентября 2011

Возможно, вы захотите постоянно читать с данного стандартного вывода, кусками по 100 байт.Затем у вас есть список потребителей - который может быть просто реализован как функции, принимающие строки / строки байтов (в зависимости от того, используете ли вы версию 2.x или 3.x).Каждый кусок отправляется каждому потребителю, а затем отбрасывается.

Примерно так:

def f_a(s): pass
def f_b(s): pass

consumers = [f_a, f_b]

while True:
    chunk = process.stdout.read(100)
    if chunk == '': break # or something like that
    for c in consumers: c(chunk)

Если вы запускаете это в потоке, вы можете изменять потребителей по своему усмотрению / необходимости.

Но вы должны позаботиться о том, чтобы потребители не блокировали, иначе ваши циклы блокируются.Это не проблема, если это не продлится слишком долго, потому что ОС дает вам довольно большой буфер между вашим подпроцессом и вами.Но это не бесконечно.Поэтому может потребоваться добавить некоторую буферизацию для каждого потребителя или в цикле.

0 голосов
/ 06 сентября 2011
import subprocess
subProc= subprocess.Popen(['tail','/dev/random'],stdout=subprocess.PIPE)
subProc.stdout[400:499] ?

или

subProc.stdout.seek(400).read(100)

, если они не работают.попробуйте:

var = subProc.stdout
var[400:499]

Также, чтобы получить правильный вывод из вашего подпроцесса, вы должны время от времени запускать flush () с Python3.X, если я не ошибаюсь: sys.stdout.flush ()

По какой-то странной причине у меня нет доступа ни к одной из моих сред Unix, поэтому я не могу на самом деле протестировать код, но теоретически это должно делать то, что вы просите.

...