TKinter windows do not appear when using multiprocessing on Linux

隐身守侯 提交于 2020-01-14 13:05:56

问题


I want to spawn another process to display an error message asynchronously while the rest of the application continues.

I'm using the multiprocessing module in Python 2.6 to create the process and I'm trying to display the window with TKinter.

This code worked okay on Windows, but running it on Linux the TKinter window does not appear if I call 'showerror("MyApp Error", "Something bad happened.")'. It does appear if I run it in the same process by calling showerrorprocess directly. Given this, it seems TKinter is working properly. I can print to the console and do other things from processes spawned by multiprocessing, so it seems to be working too.

They just don't seem to work together. Do I need to do something special to allow spawned subprocesses to create windows?

from multiprocessing import Process
from Tkinter import Tk, Text, END, BOTH, DISABLED
import sys
import traceback

def showerrorprocess(title,text):
    """Pop up a window with the given title and text. The
       text will be selectable (so you can copy it to the
       clipboard) but not editable. Returns when the
       window is closed."""
    root = Tk()
    root.title(title)
    text_box = Text(root,width=80,height=15)
    text_box.pack(fill=BOTH)
    text_box.insert(END,text)
    text_box.config(state=DISABLED)
    def quit():
        root.destroy()
        root.quit()
    root.protocol("WM_DELETE_WINDOW", quit)
    root.mainloop()

def showerror(title,text):
    """Pop up a window with the given title and text. The
       text will be selectable (so you can copy it to the
       clipboard) but not editable. Runs asynchronously in
       a new child process."""
    process = Process(target=showerrorprocess,args=(title,text))
    process.start()

Edit

The issue seems to be that TKinter was imported by the parent process, and "inherited" into the child process, but somehow its state is inextricably linked to the parent process and it cannot work in the child. So long as you make sure not to import TKinter before you spawn the child process, it will work because then it is the child process that is importing it for the first time.


回答1:


This discussion could be helpful.

Here's some sample problems I found:

  1. While the multiprocessing module follows threading closely, it's definitely not an exact match. One example: since parameters to a process must be pickleable, I had to go through a lot of code changes to avoid passing Tkinter objects since these aren't pickleable. This doesn't occur with the threading module.

  2. process.terminate() doesn't really work after the first attempt. The second or third attempt simply hangs the interpreter, probably because data structures are corrupted (mentioned in the API, but this is little consolation).




回答2:


Maybe calling the shell command xhost + before calling your program from that same shell will work?

I am guessing your problem lies with the X-server.



来源:https://stackoverflow.com/questions/410469/tkinter-windows-do-not-appear-when-using-multiprocessing-on-linux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!