退出期间的加入过程 - Tkinter +多处理

时间:2014-05-01 21:49:46

标签: python user-interface python-3.x tkinter multiprocessing

我正在编写一个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()并没有?

2 个答案:

答案 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)

我之前遇到过类似的问题(除了我没有使用多进程)。经过近一天的研究,我得出以下结论:

  1. mainloop和root.waitwindow将(有时)阻止sys.exit信号,您的程序在点击⌘Q后应该收到该信号。
  2. 您可以将⌘Q绑定到新功能,但您仍可能收到sys.exit信号
  3. 另一种方式(在我的情况下更可靠)是将tcl退出信号重新映射到另一个函数,而不是默认函数。您可以使用以下命令重新映射quit事件(dock quit和⌘Q):root.createcommand('::tk::mac::Quit',function)
  4. 尝试退出软件时,请使用sys.exit代替exit()quit()
  5. 您还可以使用root.wm_protocol("WM_DELETE_WINDOW", function)来定义用户点击红色按钮时的行为。
  6. 您实际上可以通过标记root.overridedirect(1)使窗口的边框和三个默认按钮消失,从而强制用户单击GUI上的按钮而不是关闭窗口。