2013-06-25 2 views
2

Итак, я пишу (или, по крайней мере, пытаюсь) программу для сравнения выходов двух прогонов gdb в python. Это то, что у меня есть до сих пор:Как управлять gdb с помощью подпроцесса Python.Popen?

from subprocess import * 
import subprocess 

file = raw_input('enter program name (with a ./ if in local directory): ') 

p1 = Popen(['gdb', file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
p2 = Popen(['gdb', file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

p1.communicate(input='break main') 
p2.communicate(input='break main') 

args1 = raw_input('args for running program (from file) (ie r < input.txt): ') 
args2 = raw_input('args for running program (from file) (for program 2...): ') 

p1.communicate(input=args1) 
p2.communicate(input=args2) 

while True: 
    p1out = p1.communicate(input='continue')[0] 
    p2out = p2.communicate(input='continue')[0] 

    if p1out != p2out: 
     print 'difference: ' 
     print 'p1: ' + p1out 
     print 'p2: ' + p2out 
     cont = raw_input('continue (y/n): ') 
     if cont != 'y': 
      break 

Теперь проблема в том, что это, похоже, не работает. Любые идеи о том, где я могу ошибиться?

Подробнее: Точка программы - это выполнить исполняемый файл, разбить основную функцию и затем пропустить каждый до тех пор, пока выходной сигнал не изменится между ними. Это предназначено как инструмент для отладки (который я бы использовал, даже если никто больше не будет!). Затем, когда вы находите разницу, вы даете вам возможность закончить программу или продолжить. Теоретически это должно сработать, но я просто не уверен, что происходит.

+0

вы должны избавиться от строки 'from subprocess import *' и просто создать объекты subprocess.Popen' –

ответ

2

.communicate ждет Popen объект для завершения выполнения. Поскольку вы пытаетесь поговорить с gdb, пока он работает, это будет просто вешать навсегда. gdb не собирается выходить без ввода. Кроме того, вам нужно написать новые строки, чтобы имитировать пользователя, нажав введите.

Что вы хотите сделать, это написать и прочитать из gdb во время его выполнения. Для этого используйте p1.stdin.write('break main\n') (обратите внимание на '\n') при отправке ввода и p1.stdout.readline() при считывании вывода. Это относится к разрыву в начале, аргументы, которые вы отправляете, и продолжению.

При отправке аргументов и выполнении начала, вы также должны быть уверены, что start gdb.

p1.stdin.write('start ' + args1 + '\n') 
p2.stdin.write('start ' + args2 + '\n') 

Вы также хотите обработать случай, когда один процесс завершается перед другим. Вы можете использовать Popen.poll, чтобы проверить, завершен ли процесс, он вернет None, если он этого не сделал. Несмотря на то, что это не может быть точно, как вы хотите, чтобы справиться с этим, вы можете изменить в верхней части вашего цикла, чтобы что-то вроде этого:

while True: 
    if p1.poll() is not None and p2.poll is not None: 
     print 'p1 and p2 have both finished' 
     break 
    elif p1.poll() is not None: 
     print 'p1 finished before p2' 
     break 
    elif p2.poll() is not None: 
     print 'p2 finished before p1' 
     break 

    p1.stdin.write('continue\n') 
    p2.stdin.write('continue\n') 
    p1out = p1.stdout.readline() 
    p2out = p2.stdout.readline() 

Чтение одну строку, скорее всего, не будет правильным, и вы должны будете калибровать количество строк, которые вы читаете, чтобы получить правильный результат.

Вы должны либо добавить чтение в stderr, либо отправить его на адрес /dev/null, если вам это не интересно. Если вы ничего не сделаете, буфер PIPE может заполнить и привести к зависанию.

+0

, но я помещаю эти чтения в эти переменные, разве это не помогает очистить буфер? – higgs241

+0

@ higgs241 не для 'stderr' чтения читаются только для' stdout'. Поскольку вы не используете 'stderr' ни для чего, я бы сказал, что просто выкидываем выход с помощью' Popen (..., stderr = open (os.devnull, 'w') 'при создании процесса –

+0

Я вижу , большое спасибо! – higgs241