所以我正在编写(或者至少尝试)一个程序来比较python中两个gdb运行的输出。这就是我到目前为止所做的:
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
现在问题是这似乎不起作用。关于我可能出错的地方的任何想法?
更多细节:程序的要点是接受一个可执行文件,在main函数中断,然后遍历每个函数,直到输出在两者之间变化。这是一个调试工具(我会使用,即使没有其他人会!)。然后,当您发现差异时,它会让您选择是结束程序还是继续。从理论上讲,这应该有效,但我不确定是什么搞乱了。
答案 0 :(得分:3)
.communicate
等待Popen
对象完成执行。由于你在gdb运行时试图与gdb交谈,这将永远挂起。没有任何输入,gdb不会退出。此外,您需要自己编写换行符以模拟用户点击 enter 。
你想要做的是在gdb执行时写入和读取。为此,在发送输入时使用p1.stdin.write('break main\n')
(注意'\n'
),在读取输出时使用p1.stdout.readline()
。这适用于开头的中断,你发送的args,以及继续。
在发送参数和开始执行时,您还应该确保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缓冲区可以填充并导致它挂起。