Le finestre di TKinter non vengono visualizzate quando si utilizza il multiprocessing su Linux

StackOverflow https://stackoverflow.com/questions/410469

Domanda

Voglio generare un altro processo per visualizzare un messaggio di errore in modo asincrono mentre il resto dell'applicazione continua.

Sto usando il modulo multiprocessing in Python 2.6 per creare il processo e sto provando a visualizzare la finestra con TKinter .

Questo codice ha funzionato bene su Windows, ma eseguendolo su Linux la finestra TKinter non appare se chiamo 'showerror (" Errore MyApp " ;, " Si è verificato qualcosa di brutto. " ;) '. appare se lo eseguo nello stesso processo chiamando direttamente showerrorprocess . Detto questo, sembra che TKinter funzioni correttamente. Posso stampare sulla console e fare altre cose dai processi generati da multiprocessing , quindi sembra funzionare anche.

Sembra che non funzionino insieme. Devo fare qualcosa di speciale per consentire ai sottoprocessi generati di creare finestre?

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()

Modifica

Il problema sembra essere che TKinter è stato importato dal processo padre e "ereditato" nel processo figlio, ma in qualche modo il suo stato è indissolubilmente legato al processo genitore e non può funzionare nel bambino. Fintanto che ti assicuri di non importare TKinter prima di generare il processo figlio, funzionerà perché allora è il processo figlio che lo importa per la prima volta.

È stato utile?

Soluzione

Questa discussione potrebbe essere utile.

  

Ecco alcuni problemi di esempio che ho riscontrato:

     
      
  1. Mentre il modulo multiprocessing segue da vicino il threading, non è sicuramente una corrispondenza esatta. Un esempio: poiché i parametri a   il processo deve essere selezionabile , ho dovuto passare molto codice   modifiche per evitare il passaggio di oggetti Tkinter poiché non lo sono    pickleable . Ciò non si verifica con il modulo di threading.

  2.   
  3. process.terminate () non funziona davvero dopo il primo tentativo. Il secondo o terzo tentativo semplicemente blocca l'interprete, probabilmente   perché le strutture dei dati sono danneggiate (menzionate nell'API, ma questo   è poca consolazione).

  4.   

Altri suggerimenti

Forse chiamando il comando shell xhost + prima di chiamare il tuo programma da quella stessa shell funzionerà?

Suppongo che il tuo problema risieda nell'X-server.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top