问题
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:
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.
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