-1

I have python version 3.9, I am using the default development web server that is provided by the flask on windows OS (laptop). I need to run the app on Windows machine, and it should be able to start and stop the app on demand.

Here is what I tried so far. when I run the application either in VS code, I need to force stop the app, If running in the command windows I have to kill the python app from task manager. With the following code changes I can exit the app by sending the SIGTERM to proess itself, as both the Flask, and simplehttpserver do not provide an API for exiting the process.

from flask import Flask, request, g, make_response
import queue
import time
import os
from threading import Thread
import signal
import ctypes

from multiprocessing import Process

import sys

OUTPUT_EMPTY_LIMIT = 3 
DEFAULT_PORT = 9090

SHUTDOWN    = False
EXIT_CHARS  = "Qq\x11\x18"      # 'Q', 'q', Ctrl-Q, ESC


print("Name = {}".format(__name__))

app = Flask(__name__)


def shutdown_app():
    global SHUTDOWN
    SHUTDOWN = True

@app.before_request
def before_request():
    if SHUTDOWN:
        return 'Shutting down...'
    
def run_app(port, host, debug, threaded):
    app.run(port=port, host=host, debug=debug, threaded=threaded)

    
@app.route("/")
def app_help():
    return "Hello, World from help!"

@app.route("/square/<int:number>")
def square(number):
    return str(number**2)

# This doesnt kill the app as well.
@app.route("/stop")
def stop():
    func = request.environ.get('werkzeug.server.shutdown')
    if func is None:
        raise RuntimeError('Not running with the werkzeug Server')
    func()
    return 'Server shutting down...'
    exit(0)

if __name__ == "__main__":
    port = 5000
    host = '0.0.0.0'
    debug = False
    threaded = True   
    process = Process(target=run_app, args=(port, host, debug, threaded))
    process.start()
    
    while True:
        ch = input("Enter 'Q' to stop server and exit: ")
        if (ch == 'Q'):
            break
    
    shutdown_app()
    process.terminate()
    #process.kill()
    #process.join()
    print("Exiting the app")
    # os.kill(os.getpid(), signal.SIGINT)
    os._exit(0)

I am new to Python and have tried both google search and chatGPT to find a way to shutdown Flask App and the web server that is started on a windows operating system. I have also tried the other answeres on the stack overflow 15562446

I also tried the link Shutdown The Simple Server

1 Answers1

1

I've found while testing that werkzeug.server.shutdown does nothing, and it needs to be shutdown using sys.exit(0) on my windows machine. In your code a value is returned before the exit() is run - therefore it does not shut down. One way to do what you want is using deferred callbacks.

from flask import after_this_request 

@app.get('/stop')
def shutdown():
    @after_this_request
    def response_processor(response):
        @response.call_on_close
        def shutdown():
            import sys
            sys.exit("Stop API Called")
        return response
    return 'Server shutting down...',200
arrmansa
  • 518
  • 10
  • I tried this code, and it did not work as well. The python program in the command prompt continues to run, I do get the response "Server shutting down..." to the "curl localhost:5000/stop". To check if the shutdown is called I put a breakpoint and it seems to call the shutdown, but then an exception is raised. `Exception has occurred: SystemExit Stop API Called File "\app.py", line XX, in shutdown sys.exit("Stop API Called") SystemExit: Stop API Called` – Amit Bhatia Feb 14 '23 at 13:03
  • I checked the code to sys.exit(0) to bypass the exception, but the python program still continues to run, as the attached process (flask or webserver) is still running. – Amit Bhatia Feb 14 '23 at 13:07
  • 1. Could you try os._exit() instead of sys.exit ? 2. Also what version of python and flask are you using? – arrmansa Feb 15 '23 at 03:01
  • I was using Threaded = False in my server. In your case sys.exit() might be getting called from a different thread, leading to this issue. If so, os._exit() should work. – arrmansa Feb 15 '23 at 03:11
  • I tried both os._exit(0) and os.kill(os.getpid(), signal.SIGTERM), but they both kill the subprocess. Not the main process. I also added process.terminate() and os._exit(0) in the end of progam, and then it can exit if I enter 'Q' to quit the program. – Amit Bhatia Feb 17 '23 at 20:08
  • I marked the question as answered as with the comments the program works, # This doesnt kill the app only the subprocess. ```@app.get('/stop') def shutdown(): @after_this_request def response_processor(response): @response.call_on_close def shutdown(): import os os._exit(0) return response return 'Server shutting down...',200``` – Amit Bhatia Feb 17 '23 at 20:16
  • The following kills the process. if __name__ == "__main__": port = DEFAULT_PORT host = '0.0.0.0' debug = False threaded = True process = Process(target=run_app, args=(port, host, debug, threaded)) process.start() while True: ch = input("Enter 'Q' to stop server and exit: ") if (ch == 'Q'): break print("Exiting the app") shutdown_app() process.terminate() os._exit(0) – Amit Bhatia Feb 17 '23 at 20:17