子进程完成后为按钮着色

时间:2009-12-12 14:40:35

标签: python subprocess gnome tk

我有一个Tk python程序,它在当前目录中创建一个python文件列表,并为每个文件生成一个按钮。当您单击一个按钮时,相应的python程序将通过新的gnome-terminal中的子进程启动。子进程在新终端上执行完毕后,我想将按钮的颜色切换为红色。不幸的是,按钮几乎立即改变颜色。

from Tkinter import *
import os, subprocess

root = Tk()
buttonsD = {}

def launch(ourfile):
    p=subprocess.Popen(["gnome-terminal","-e","python " + ourfile], shell=False)
    buttonsD[ourfile].configure(bg='red')

dirlist=os.listdir(os.getcwd())
for fname in dirlist:
    if fname.endswith('py') and fname != 'gui2.py':
        buttonsD[fname] = Button(root,text=fname,command=lambda i=fname: launch(i))
        buttonsD[fname].pack(side=TOP,expand=YES,fill=BOTH)

root.mainloop()

几乎立刻意味着我可以等到p.poll == None,并且看到创建gnome-terminal需要一点时间。但是一旦创建了终端,即使进程仍在新终端中运行,该按钮也会变为红色。我无法创建一个新的gnome-terminal然后传达我想要运行的进程。似乎gnome-terminal只是创建了一个新的bash实例,然后返回done,所以如果我尝试与它的stdin进行通信就会出现管道错误。

2 个答案:

答案 0 :(得分:1)

这里有两个问题:用于在gnome-terminal中启动Python程序的命令行,以及如何在Tkinter应用程序中使用subprocess。我只知道后者。

subprocess.Popen立即返回,这就是按钮立即变为红色的原因。我想你可能需要列出正在运行的程序。然后编写一个函数poll_processes,在每个正在运行的进程上调用poll(),当结果不是None时,将其从列表中删除并将按钮变为红色。

然后您要做的就是安排Tkinter定期调用该功能,您可以致电frame.after(msec, poll_processes)安排第一次拨打poll_processes,然后让poll_processes做安排下次通话也是一样。

答案 1 :(得分:1)

我相信gnome终端正在进行双分叉,以便将自己从其父进程组中分离出来 - 所以实际上你的子进程几乎立即终止,正如你所观察到的那样,一切都发生在你的另一个后代无法直接访问。

不幸的是我不相信gnome终端提供任何方法来禁用这种双叉行为;因此,要找出“进一步后代”何时完成,您必须确定该过程并定期监控。与它直接交互也是一个相当高的顺序 - 与任何与你无关的任何“随机”过程交互都不容易: - (。