flask: stop server after exception

Question:

I would like to stop my flask server as soon as an unhandled exception occurs.
Here is an example:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    1/0 # argh, exception
    return 'Hello World!'


if __name__ == '__main__':
    app.run(port=12345)

If you run this and go to localhost:12345, your browser tells you “internal server error” and the python console logs a DivisionByZero exception.

But the server app doesn’t crash. Flask wraps your routes into its own error handling and it only prints the exception.

I would like to make the server stop as soon as a route produces an exception. But I didn’t find this behaviour in the API. You can specify an errorhandler but that is only to give custom error messages to the client after your route failed.

Asked By: lhk

||

Answers:

Stopping Flask requires getting into Werkzeug internals. See http://flask.pocoo.org/snippets/67/

Extracted from a single-user app:

from flask import request

@app.route('/quit')
def shutdown():
    ...
    shutdown_hook = request.environ.get('werkzeug.server.shutdown')
    if shutdown_hook is not None:
        shutdown_hook()
    return Response("Bye", mimetype='text/plain')

The shutdown_hook bit is what you’d need in an exception handler.

Answered By: Dave W. Smith
from multiprocessing import Process

server = Process(target=app.run)
server.start()
# ...
server.terminate()
server.join()

or if Threaded to run Flask Web Server in background around other python code:

import threading
import ctypes
webserverurl  = 127.0.0.1
webserverport = 8080

    class thread_with_exception(threading.Thread):
        def __init__(self, name):
            threading.Thread.__init__(self)
            self.name = name
            self.interval = 1
            self.daemon = True
    
        def __del__(self):
            print(f"Thread terminated");
    
        def run(self):
            # target function of the thread class
            try:
                while True:
                    print(f"{self.name} Waiting for Web")
                    app.run(host=webserverurl, port=webserverport)
            finally:
                print('ended')
    
        def get_id(self):
            # returns id of the respective thread
            if hasattr(self, '_thread_id'):
                return self._thread_id
            for id, thread in threading._active.items():
                if thread is self:
                    return id
    
        def raise_exception(self):
            thread_id = self.get_id()
            res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), ctypes.py_object(SystemExit))
            print(f"{self.name} terminated")
            if res > 1:
                ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), 0)
                print('Exception raise failure')

t1 = thread_with_exception('Web Server 1')
t1.start()
time.sleep(10)
t1.raise_exception()
# del t1

credit to Andrew Abrahamowicz here:
https://code.activestate.com/recipes/496960-thread2-killable-threads

ctypes.c_long( required for Linux else Windows only: https://stackoverflow.com/a/61638782/3426192

Answered By: social
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.