2013-11-25 3 views
3

Я пытаюсь разобрать в реальном времени выходные данные программной буферизации, что означает, что выход недоступен до тех пор, пока процесс не завершится. Мне нужно просто разбирать строки за строкой, фильтровать и управлять данными с выхода, поскольку это может работать в течение нескольких часов.Parsing pexpect output

Я попытался захватить вывод с помощью subprocess.Popen(), но да, как вы можете догадаться, Popen не может управлять таким поведением, он сохраняет буферизацию до конца процесса.

from subprocess import Popen, PIPE 

p = Popen("my noisy stuff ", shell=True, stdout=PIPE, stderr=PIPE) 
for line in p.stdout.readlines(): 
    #parsing text and getting data 

Так что я нашел pexpect, который печатает вывод в режиме реального времени, так как она обрабатывает стандартный вывод в файл, или я мог бы даже сделать пакость печать из файла и разборе его вне функции. Но хорошо, что это слишком грязно, даже для меня;)

import pexpect 
import sys 

pexpect.run("my noisy stuff", logfile=sys.stdout) 

Но я предполагаю, что это должно лучший вещий способ сделать это, просто управлять STDOUT как подпроцесс. Попэн делает. Как я могу это сделать?

EDIT:

Запуск J.F. предложение:

Это сознательно неправильно аудит, это занимает около 25 секунд. остановиться.

from subprocess import Popen, PIPE 

command = "bully mon0 -e ESSID -c 8 -b aa:bb:cc:dd:ee:00 -v 2" 

p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE) 

for line in iter(p.stdout.readline, b''): 
    print "inside loop" 
    print line 

print "outside loop" 
p.stdout.close() 
p.wait() 


#$ sudo python SCRIPT.py 
           ### <= 25 secs later...... 
# inside loop 
#[!] Bully v1.0-21 - WPS vulnerability assessment utility 

#inside loop 
#[!] Using 'ee:cc:bb:aa:bb:ee' for the source MAC address 

#inside loop 
#[X] Unable to get a beacon from the AP, possible causes are 

#inside loop 
#[.] an invalid --bssid or -essid was provided, 

#inside loop 
#[.] the access point isn't on channel '8', 

#inside loop 
#[.] you aren't close enough to the access point. 

#outside loop 

Используя этот метод вместо: EDIT: Из-за большие задержки и перерывы в выходе, я должен был исправить ребенок, и добавил некоторые хаки, поэтому окончательный код выглядит следующим образом

import pexpect 

child = pexpect.spawn(command) 
child.maxsize = 1 #Turns off buffering 
child.timeout = 50 # default is 30, insufficient for me. Crashes were due to this param. 
for line in child: 
    print line, 

child.close() 

Возвращает тот же результат, но он печатает строки в режиме реального времени. Итак ... SOLVED Спасибо @ J.F. Себастьян

+1

Связанный: [Python subprocess readlines() зависает] (http://stackoverflow.com/q/12419198/4279) – jfs

+1

Связанный: [Python: чтение потокового ввода из subprocess.communicate()] (http: // stackoverflow .com/q/2715847/4279) – jfs

+1

Вам нужно отправить ответы на команду или просто прочитать результат? Вам нужен вывод с линейной буферизацией или выход с буферизацией с блочным буфером (например, с использованием 4096-байтового буфера), достаточный для программы, которая может работать несколько часов? – jfs

ответ

2

.readlines() читает все линии. Неудивительно, что вы не видите любой вывод до конца подпроцесса. Вы можете использовать .readline() вместо того, чтобы построчно прочитать как только подпроцесс переполняется стандартный вывод буфера:

from subprocess import Popen, PIPE 

p = Popen("my noisy stuff", stdout=PIPE, bufsize=1) 
for line in iter(p.stdout.readline, b''): 
    # process line 
    .. 
p.stdout.close() 
p.wait() 

Если вы уже pexpect, то вы можете использовать его, чтобы обойти эту проблему блок-буферную:

import pexpect 

child = pexpect.spawn("my noisy stuff", timeout=None) 
for line in child: 
    # process line 
    .. 
child.close() 

См. Также stdbuf, pty -based solutions из вопроса, который я связал в комментариях.

+0

Этот код по-прежнему не работает, потому что некоторые приложения имеют выходной буфер с буферизацией, поэтому единственный способ потока из буфера - это запуск команд из псевдо-pty. Я видел другие комментарии от вас в S.Overf. и я пробовал все их, прежде чем спрашивать;). Pexpect был единственным методом, который работал ... как искусно. – peluzza

+1

@peluzza: Я явно добавил решение 'pexpect'. Не могли бы вы обновить свой вопрос, чтобы предоставить полный минимальный пример, демонстрирующий, что «не работает» означает в вашем конкретном случае код «subprocess» из моего ответа? (например, '' мой шумный материал ''' '{echo a; sleep 2; echo b;}', shell = True', и очень важно получить' 'a'', не дожидаясь' 2' секунд. – jfs

+0

Отредактировано , i вставной вывод термина. В любом случае ваше решение pexpect работает как шарм. Печать результатов в режиме реального времени. Огромное спасибо.!!! – peluzza

Смежные вопросы