我正在编写一个GUI应用程序,它有一个调用长任务的按钮。为了不冻结GUI,我使用python 3.3的多处理模块将任务委托给不同的进程。然后我使用Pipe返回显示结果。
我希望应用程序即使在计算过程中退出也不会留下任何僵尸进程。当我在Mac上时,这可以通过以下两种方式之一发生:退出应用程序(Command + Q)或关闭它的窗口。
这里是链接到GUI中按钮的函数中的代码:
main_pipe,child_pipe=Pipe()
p=Process(target=worker,args=(child_pipe,data))
p.start()
try:
while not main_pipe.poll():
root.update()
value_array=main_pipe.recv()
finally:
p.join()
这不起作用,应用程序没有响应Command + q,关闭窗口会使两个僵尸进程运行(一个用于GUI,一个用于工作者)。
如何在其他情况下使其工作? 这是好习惯吗?这是一种更好,更pythonic的做法吗?
此外,在脚本的最后,我有两行(如果窗口关闭而不处理任何内容,exit()将关闭应用程序):
root.mainloop()
exit()
最后,update()和mainloop()之间的区别是什么?仅仅是后者在程序中占用了程序,而update()并没有?
答案 0 :(得分:0)
好的,我终于解决了。虽然我没有完全确定这种方法的pythoness或副作用,但如果有人需要它,那就是。
我认为正确退出只能发生在一个mainloop()而不是update()中,所以我写了两个函数,一个用于创建进程,另一个用于检查它的输出,它们互相调用root.after()。我将进程守护进程标志设置为true以确保正确的退出行为。这是代码:
def process_start():
global value_array
global main_pipe
main_pipe,child_pipe = Pipe()
p=Process(target=worker,args=(child_pipe,data))
p.daemon=True
p.start()
root.after(500,check_proc)
def check_proc():
if not main_pipe.poll():
root.after(500,check_proc)
else:
global value_array
value_array=main_pipe.recv()
我仍然不确定是否需要p.join()但是deamon似乎绕过了僵尸程序问题
答案 1 :(得分:0)
我之前遇到过类似的问题(除了我没有使用多进程)。经过近一天的研究,我得出以下结论:
root.waitwindow
将(有时)阻止sys.exit信号,您的程序在点击⌘Q后应该收到该信号。 root.createcommand('::tk::mac::Quit',function)
sys.exit
代替exit()
或quit()
root.wm_protocol("WM_DELETE_WINDOW", function)
来定义用户点击红色按钮时的行为。 root.overridedirect(1)
使窗口的边框和三个默认按钮消失,从而强制用户单击GUI上的按钮而不是关闭窗口。