Python Flask: getting an error when server shutdown is declined

I am a newbie at FLask. I am building an app which uses Flask as framework. the app and server is supposed to work only on localhost.

When exiting the app I also want to shutdown the server.

I found the nice way to stop the server here http://web.archive.org/web/20190706125149/http://flask.pocoo.org/snippets/67

I placed a button in the htmll layout header (so it’s there on all the pages) that uopn clicking shows a Tkinter dialog box. Now, before shutting down the server the app asks the user to confirm the action. No problems shutting down, all goes as expected. But answering “No” to the messagebox I created (Tkinter), makes that the second time I try to use the Exit button I get an error message.

here is my code.

Python:

from flask import Flask, render_template, url_for, request, url_for, redirect
from tkinter import filedialog, messagebox
from tkinter import *

app = Flask(__name__)

def dialog_yn(title="mesage Box", prompt="Make your choice"):
    Tk().withdraw()
    result = messagebox.askquestion(title=title,message=prompt,icon='warning')
    return result

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/shutdown', methods=['GET'])
def shutdown():
    answer = dialog_yn('Exit Configurator', 'Do you really want to quit the configurator?')
    print(answer)
    if answer == 'yes':
        shutdown_server()
        return 'Server shutting down...'
    else:
        return redirect(url_for('index'))

def shutdown_server():
    func = request.environ.get('werkzeug.server.shutdown')
    if func is None:
        raise RuntimeError('Not running with the Werkzeug Server')
    func()

if __name__ == "__main__":
    app.run(debug=True)

Upon annswering no everything seems to go back to the index page. the error actually triggers the second time I hit the exit button (submit button in a dummy form). Did I already say that?
the error I get is

  File "E:Python_ScriptsTODO__listapp.py", line 24, in shutdown
    answer = dialog_yn('Exit Configurator', 'Do you really want to quit the configurator?')
  File "E:Python_ScriptsTODO__listapp.py", line 13, in dialog_yn
    result = messagebox.askquestion(title=title,message=prompt,icon='warning')
  File "C:Usersdefault_userAppDataLocalProgramsPythonPython38Libtkintermessagebox.py", line 99, in askquestion
    return _show(title, message, QUESTION, YESNO, **options)
  File "C:Usersdefault_userAppDataLocalProgramsPythonPython38Libtkintermessagebox.py", line 72, in _show
    res = Message(**options).show()
  File "C:Usersdefault_userAppDataLocalProgramsPythonPython38Libtkintercommondialog.py", line 40, in show
    w = Frame(self.master)
  File "C:Usersdefault_userAppDataLocalProgramsPythonPython38Libtkinter__init__.py", line 3119, in __init__
    Widget.__init__(self, master, 'frame', cnf, {}, extra)
  File "C:Usersdefault_userAppDataLocalProgramsPythonPython38Libtkinter__init__.py", line 2567, in __init__
    self.tk.call(
RuntimeError: main thread is not in main loop

What am I doing wrong? As I said I am starting with Flask (and Tkinter for that matter), so go easy on me. thnx for the patience.

Answer

You need to destroy the Tk() instance after closing the messagebox:

def dialog_yn(title="mesage Box", prompt="Make your choice"):
    root = Tk()
    root.withdraw()
    result = messagebox.askquestion(title=title, message=prompt, icon='warning')
    root.destroy()
    return result