我有一个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进行通信就会出现管道错误。
答案 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终端提供任何方法来禁用这种双叉行为;因此,要找出“进一步后代”何时完成,您必须确定该过程并定期监控。与它直接交互也是一个相当高的顺序 - 与任何与你无关的任何“随机”过程交互都不容易: - (。