Невозможно выйти из скрипта Python из приложения tkinter при использовании `wait_variable ()` - PullRequest
3 голосов
/ 16 мая 2019

У меня есть код Python, который включает в себя окно tkinter и другие выполняющиеся задачи.

Я пытался связать событие "WM_DELETE_WINDOW" с функцией, которая закрывает мой код Python, когда я закрываю окно, ноЯ не могу этого достичь.

Вот что я пытаюсь:

def on_exit():
    root.destroy()
    sys.exit()
root.protocol('WM_DELETE_WINDOW', on_exit)

Окно успешно уничтожено, но код python не завершается.Любая возможная причина, по которой sys.exit() не работает?

Что я делаю не так?какой альтернативный подход я должен попробовать?

Проведя некоторое тестирование, я выяснил, в чем может быть проблема.

Вот небольшой код, который суммирует мой код, который намного больше.

import tkinter as tk
import sys

root = tk.Tk()
submitted = tk.IntVar()

def on_exit():
    root.destroy()
    sys.exit()
root.protocol('WM_DELETE_WINDOW', on_exit)

def submit():
    submitted.set(1)
    print("submitted")

button= tk.Button(root, text="Submit",command=submit)
button.pack()
button.wait_variable(submitted)

root.mainloop()

Теперь я считаю, чтоwait_variable является источником проблемы.

И код фактически завершается, когда я добавил submitted.set(1) к on_exit() (или если я сначала нажал кнопку перед закрытием окна), но если я попытался закрытьокно без нажатия кнопки, код не выйдет.

Значит ли это, что wait_variable не только заставляет приложение tkinter ждать, но и предотвращает выход кода Python?!

Я пыталсяos._exit(1) и это сработало, но я думаю, что это не чисто.

Спасибо

1 Ответ

2 голосов
/ 16 мая 2019

Поскольку ваш обновленный вопрос указывает на проблему wait_variable().Уходя из документации по этому методу wait_variable() входит в локальный цикл обработки событий, который не прерывает mainloop, однако кажется, что до тех пор, пока этот локальный цикл обработки событий не прекратится (переменная каким-либо образом обновляется), он будет препятствовать завершению экземпляра Python.так как еще есть активный цикл.Поэтому, чтобы предотвратить это, вы также правильно указали, что вам нужно обновить эту переменную прямо перед завершением экземпляра tk.

Это может показаться странным, но это поведение, которое я ожидал бы.Насколько я понимаю, активный цикл должен быть прерван до того, как экземпляр Python сможет завершиться.

Как отметил Брайан в комментариях, метод wait_variable() - это функция, которая вызывает vwait *Команда 1010 * во встроенном интерпретаторе tcl. Этот интерпретатор tcl ничего не знает об исключениях python, поэтому, вероятно, он не распознает исключение python, вызванное sys.exit () "

Ссылка на соответствующую документацию:

wait_variable ()

Восстановить текст по ссылке:

wait_variable (name)

Ожидает, когда данная переменная Tkinter будетменять.Этот метод входит в локальный цикл обработки событий, поэтому другие части приложения по-прежнему будут реагировать.Локальный цикл обработки событий завершается, когда переменная обновляется (также учитывается ее текущее значение).

Вы также можете установить переменную на значение, установленное в данный момент, чтобы завершить этот цикл обработки событий.

Эта строка должна работать для вас:

submitted.set(submitted.get())

При этом вам не нужно sys.exit().Вы можете просто использовать root.destroy().

Ваша новая функция должна выглядеть следующим образом:

def on_exit():
    submitted.set(submitted.get())
    root.destroy()

Экземпляр python автоматически закроется, если после mainloop больше не будет кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...