Окна TKinter не отображаются при использовании многопроцессорности в Linux - PullRequest
4 голосов
/ 04 января 2009

Я хочу порождать другой процесс для асинхронного отображения сообщения об ошибке, пока остальная часть приложения продолжается.

Я использую модуль multiprocessing в Python 2.6 для создания процесса и пытаюсь отобразить окно с TKinter.

Этот код хорошо работал в Windows, но при запуске в Linux окно TKinter не появляется, если я вызываю 'showerror("MyApp Error", "Something bad happened.")'. появляется , если я запускаю его в том же процессе, вызывая showerrorprocess напрямую. Учитывая это, кажется, TKinter работает правильно. Я могу печатать на консоль и делать другие вещи из процессов, порожденных multiprocessing, так что, похоже, он тоже работает.

Кажется, они просто не работают вместе. Нужно ли делать что-то особенное, чтобы порожденные подпроцессы могли создавать окна?

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

Редактировать

Кажется, проблема в том, что TKinter был импортирован родительским процессом и «унаследован» в дочернем процессе, но каким-то образом его состояние неразрывно связано с родительским процессом и не может работать в дочернем. До тех пор, пока вы убедитесь, что не импортировали TKinter, прежде чем вызывать дочерний процесс, он будет работать, потому что тогда это будет дочерний процесс, который импортирует его впервые.

Ответы [ 2 ]

4 голосов
/ 12 января 2009

Это обсуждение может быть полезным.

Вот несколько примеров проблем, которые я нашел:

  1. Хотя многопроцессорный модуль тесно связан с многопоточностью, он точно не является точным соответствием. Один пример: так как параметры в процесс должен быть маринованным , мне пришлось пройти через много кода изменения, чтобы избежать передачи Tkinter объектов, так как они не pickleable . Это не происходит с модулем потоков.

  2. process.terminate() на самом деле не работает после первой попытки. Вторая или третья попытка просто вешает переводчика, наверное потому что структуры данных повреждены (упоминается в API, но это это небольшое утешение).

0 голосов
/ 04 января 2009

Может быть, вызов команды оболочки xhost + перед вызовом вашей программы из той же оболочки будет работать?

Полагаю, ваша проблема в X-сервере.

...