janelas tkinter não aparece quando se utiliza multiprocessamento no Linux
-
03-07-2019 - |
Pergunta
Eu quero gerar outro processo para exibir uma mensagem de erro de forma assíncrona, enquanto o resto do aplicativo continua.
Eu estou usando o módulo multiprocessing
em Python 2.6 para criar o processo e eu estou tentando exibir a janela com TKinter
.
Este código funcionou bem no Windows, mas executá-lo no Linux janela TKinter
não aparecer se eu chamar 'showerror("MyApp Error", "Something bad happened.")'
. É não aparecer se eu executá-lo no mesmo processo, chamando showerrorprocess
diretamente. Diante disso, parece TKinter
está funcionando corretamente. Posso imprimir no console e fazer outras coisas de processos gerados por multiprocessing
, por isso parece estar funcionando também.
Eles simplesmente não parecem funcionar em conjunto. Preciso fazer algo especial para permitir subprocessos desovado para criar janelas?
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()
Editar
O problema parece ser que TKinter
foi importado pelo processo pai, e "herdou" no processo de criança, mas de alguma forma o seu estado está intrinsecamente ligado ao processo de pai e ele não pode trabalhar na criança. Enquanto a certeza de não fazer a TKinter
de importação antes de você gerar o processo filho, ele vai trabalhar, porque então é o processo filho que é importá-lo pela primeira vez.
Solução
Este discussão poderia ser útil.
Eis alguns exemplos de problemas que encontrei:
Enquanto o módulo de multiprocessamento segue enfiar perto, definitivamente não é uma correspondência exata. Um exemplo: uma vez que os parâmetros para a processo deve ser pickle , eu tinha que passar por um monte de código mudanças para evitar passar objetos
Tkinter
uma vez que estes não são pickle . Isso não ocorre com o módulo de threading.
process.terminate()
realmente não funciona após a primeira tentativa. A segunda ou terceira tentativa simplesmente trava o intérprete, provavelmente porque estruturas de dados estão corrompidos (mencionado na API, mas este é pouco consolo).
Outras dicas
Talvez chamando o xhost +
comando shell antes de chamar o seu programa a partir dessa mesma shell vai funcionar?
Eu estou supondo que suas mentiras problema com o X-servidor.