想法是在子进程行中运行命令,将整个输出发送到一个tkinter文本小部件(outputText)并搜索输出,如果适用,则将信息写入另一个tkinter文本小部件(inputText)。请参阅此代码部分:
if (v1.get()) == 1:
reply = subprocess.Popen("c:\delprof2\DelProf2.exe /c:" + machineName, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data, error = reply.communicate()
outputText.insert("end", data)
for line in reply.stdout:
if line.strip() == "The following user profiles match the deletion criteria:":
inputText.insert("end", machineName + " has matching profiles" + "\n")
和本节:
if (v1.get()) == 1:
reply = subprocess.Popen("c:\delprof2\DelProf2.exe /c:" + machineName, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for line in reply.stdout:
if line.strip() == "The following user profiles match the deletion criteria:":
inputText.insert("end", machineName + " has matching profiles" + "\n")
data, error = reply.communicate()
outputText.insert("end", data)
正如您所看到的,除了线条的运行顺序之外,它们是相同的。在这两个示例中,只会执行代码的第一部分,而不会执行第二部分。就像线条在stdout上战斗一样,无论哪个都先跑了! 我需要改变什么来让它们都起作用?
谢谢!
答案 0 :(得分:1)
两个代码示例都不正确。 for line in process.stdout
和process.communicate()
都使用所有子进程'stdout。
两个方法都会阻塞,直到子进程完成写入 - 它可能会冻结您的GUI - 您应该将代码放入单独的(来自GUI)线程或使用异步I / O.这是代码示例,演示如何get subprocess' output using a background thread。这是the same using async. I/O (*nix)。
要一次将输出插入两个地方,您可以修改the multithreaded code example中的update()
方法,以便在必要时为每行和小部件调用.insert()
。
注意:如果要重定向stdout / stderr(如代码中那样),则需要同时读取两个流,否则可能出现死锁。如果你需要stderr然后创建一个单独的线程来读取(类似于stdout的线程)或者用.createfilehandler()
方法注册一个读处理程序(仅限* nix)。
答案 1 :(得分:0)
因为正如J.F. Sebastian所说,.stdout& .communicate()使用进程' stdout,你的问题类似于使用python生成器:你只能得到进程'输出一次。
解决方案?如果我正确理解你的问题,那么你只想使用该过程的输出两次。在这种情况下,将其分配给变量一次,并根据需要多次调用该变量。 e.g:
第1节:
if (v1.get()) == 1:
reply = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data, error = reply.communicate()
outputText.insert("end", data)
for line in data: # the stdout is in data! reply.stdout won't be useful here since you called .communicate()
# do stuff with data
或者,在第2节:
if (v1.get()) == 1:
reply = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data = reply.stdout # you can call this variable as many times as you want and it will return the same data
for line in data:
inputText.insert("end", machineName + " has matching profiles" + "\n")
# data, error = reply.communicate() <-- this would reset data to ''
outputText.insert("end", data)
以下是重置数据的示例:
x = subprocess.Popen("echo ok", stdout=subprocess.PIPE, shell=True)
for line in x.stdout:
print line
# this prints "ok", as expected
tup = x.communicate()
tup == ('', None) # This is True, since x.stdout consumed the output
这会回答你的问题吗?