How to stop flask application without using ctrl-c
PythonFlaskFlask ExtensionsPython Problem Overview
I want to implement a command which can stop flask application by using flask-script.
I have searched the solution for a while. Because the framework doesn't provide app.stop()
API, I am curious about how to code this. I am working on Ubuntu 12.10 and Python 2.7.3.
Python Solutions
Solution 1 - Python
If you are just running the server on your desktop, you can expose an endpoint to kill the server (read more at Shutdown The Simple Server):
from flask import request
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
@app.get('/shutdown')
def shutdown():
shutdown_server()
return 'Server shutting down...'
Here is another approach that is more contained:
from multiprocessing import Process
server = Process(target=app.run)
server.start()
# ...
server.terminate()
server.join()
Let me know if this helps.
Solution 2 - Python
I did it slightly different using threads
from werkzeug.serving import make_server
class ServerThread(threading.Thread):
def __init__(self, app):
threading.Thread.__init__(self)
self.server = make_server('127.0.0.1', 5000, app)
self.ctx = app.app_context()
self.ctx.push()
def run(self):
log.info('starting server')
self.server.serve_forever()
def shutdown(self):
self.server.shutdown()
def start_server():
global server
app = flask.Flask('myapp')
# App routes defined here
server = ServerThread(app)
server.start()
log.info('server started')
def stop_server():
global server
server.shutdown()
I use it to do end to end tests for restful api, where I can send requests using the python requests library.
Solution 3 - Python
This is a bit old thread, but if someone experimenting, learning, or testing basic flask app, started from a script that runs in the background, the quickest way to stop it is to kill the process running on the port you are running your app on. Note: I am aware the author is looking for a way not to kill or stop the app. But this may help someone who is learning.
sudo netstat -tulnp | grep :5001
You'll get something like this.
> tcp 0 0 0.0.0.0:5001 0.0.0.0:* LISTEN 28834/python
To stop the app, kill the process
sudo kill 28834
Solution 4 - Python
My method can be proceeded via bash terminal/console
-
run and get the process number
$ ps aux | grep yourAppKeywords
2a) kill the process
$ kill processNum
2b) kill the process if above not working
$ kill -9 processNum
Solution 5 - Python
As others have pointed out, you can only use werkzeug.server.shutdown
from a request handler. The only way I've found to shut down the server at another time is to send a request to yourself. For example, the /kill
handler in this snippet will kill the dev server unless another request comes in during the next second:
import requests
from threading import Timer
from flask import request
import time
LAST_REQUEST_MS = 0
@app.before_request
def update_last_request_ms():
global LAST_REQUEST_MS
LAST_REQUEST_MS = time.time() * 1000
@app.post('/seriouslykill')
def seriouslykill():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
return "Shutting down..."
@app.post('/kill')
def kill():
last_ms = LAST_REQUEST_MS
def shutdown():
if LAST_REQUEST_MS <= last_ms: # subsequent requests abort shutdown
requests.post('http://localhost:5000/seriouslykill')
else:
pass
Timer(1.0, shutdown).start() # wait 1 second
return "Shutting down..."
Solution 6 - Python
This is an old question, but googling didn't give me any insight in how to accomplish this.
Because I didn't read the code here properly! (Doh!)
What it does is to raise a RuntimeError
when there is no werkzeug.server.shutdown
in the request.environ
...
So what we can do when there is no request
is to raise a RuntimeError
def shutdown():
raise RuntimeError("Server going down")
and catch that when app.run()
returns:
...
try:
app.run(host="0.0.0.0")
except RuntimeError, msg:
if str(msg) == "Server going down":
pass # or whatever you want to do when the server goes down
else:
# appropriate handling/logging of other runtime errors
# and so on
...
No need to send yourself a request.
Solution 7 - Python
If you're working on the CLI and only have one flask app/process running (or rather, you just want want to kill any flask process running on your system), you can kill it with:
kill $(pgrep -f flask)
Solution 8 - Python
If you're outside the request-response handling, you can still:
import os
import signal
sig = getattr(signal, "SIGKILL", signal.SIGTERM)
os.kill(os.getpid(), sig)
Solution 9 - Python
You don't have to press CTRL + C, but you can provide an endpoint which does it for you:
from flask import Flask, jsonify, request
import json, os, signal
@app.route('/stopServer', methods=['GET'])
def stopServer():
os.kill(os.getpid(), signal.SIGINT)
return jsonify({ "success": True, "message": "Server is shutting down..." })
Now you can just call this endpoint to gracefully shutdown the server:
curl localhost:5000/stopServer
Solution 10 - Python
If someone else is looking how to stop Flask server inside win32 service - here it is. It's kinda weird combination of several approaches, but it works well. Key ideas:
- These is
shutdown
endpoint which can be used for graceful shutdown. Note: it relies onrequest.environ.get
which is usable only inside web request's context (inside@app.route
-ed function) - win32service's
SvcStop
method usesrequests
to do HTTP request to the service itself.
myservice_svc.py
import win32service
import win32serviceutil
import win32event
import servicemanager
import time
import traceback
import os
import myservice
class MyServiceSvc(win32serviceutil.ServiceFramework):
_svc_name_ = "MyServiceSvc" # NET START/STOP the service by the following name
_svc_display_name_ = "Display name" # this text shows up as the service name in the SCM
_svc_description_ = "Description" # this text shows up as the description in the SCM
def __init__(self, args):
os.chdir(os.path.dirname(myservice.__file__))
win32serviceutil.ServiceFramework.__init__(self, args)
def SvcDoRun(self):
# ... some code skipped
myservice.start()
def SvcStop(self):
"""Called when we're being shut down"""
myservice.stop()
# tell the SCM we're shutting down
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STOPPED,
(self._svc_name_, ''))
if __name__ == '__main__':
os.chdir(os.path.dirname(myservice.__file__))
win32serviceutil.HandleCommandLine(MyServiceSvc)
myservice.py
from flask import Flask, request, jsonify
# Workaround - otherwise doesn't work in windows service.
cli = sys.modules['flask.cli']
cli.show_server_banner = lambda *x: None
app = Flask('MyService')
# ... business logic endpoints are skipped.
@app.route("/shutdown", methods=['GET'])
def shutdown():
shutdown_func = request.environ.get('werkzeug.server.shutdown')
if shutdown_func is None:
raise RuntimeError('Not running werkzeug')
shutdown_func()
return "Shutting down..."
def start():
app.run(host='0.0.0.0', threaded=True, port=5001)
def stop():
import requests
resp = requests.get('http://0.0.0.0:5001/shutdown')
Solution 11 - Python
You can use method bellow
app.do_teardown_appcontext()
Solution 12 - Python
request.environ.get
deprecated.
Pavel Minaev solution is pretty clear:
import os
from flask import Flask
app = Flask(__name__)
exiting = False
@app.route("/exit")
def exit_app():
global exiting
exiting = True
return "Done"
@app.teardown_request
def teardown(exception):
if exiting:
os._exit(0)
Solution 13 - Python
Google Cloud VM instance + Flask App
I hosted my Flask Application on Google Cloud Platform Virtual Machine.
I started the app using python main.py
But the problem was ctrl+c did not work to stop the server.
This command $ sudo netstat -tulnp | grep :5000
terminates the server.
My Flask app runs on port 5000 by default.
Note: My VM instance is running on Linux 9.
It works for this. Haven't tested for other platforms. Feel free to update or comment if it works for other versions too.
Solution 14 - Python
A Python solution
Run with: python kill_server.py
.
This is for Windows only. Kills the servers with taskkill, by PID, gathered with netstat.
# kill_server.py
import os
import subprocess
import re
port = 5000
host = '127.0.0.1'
cmd_newlines = r'\r\n'
host_port = host + ':' + str(port)
pid_regex = re.compile(r'[0-9]+$')
netstat = subprocess.run(['netstat', '-n', '-a', '-o'], stdout=subprocess.PIPE)
# Doesn't return correct PID info without precisely these flags
netstat = str(netstat)
lines = netstat.split(cmd_newlines)
for line in lines:
if host_port in line:
pid = pid_regex.findall(line)
if pid:
pid = pid[0]
os.system('taskkill /F /PID ' + str(pid))
# And finally delete the .pyc cache
os.system('del /S *.pyc')
If you are having trouble with favicon / changes to index.html loading (i.e. old versions are cached), then try "Clear Browsing Data > Images & Files" in Chrome as well.
Doing all the above, and I got my favicon to finally load upon running my Flask app.
Solution 15 - Python
app = MyFlaskSubclass()
...
app.httpd = MyWSGIServerSubclass()
...
@app.route('/shutdown')
def app_shutdown():
from threading import Timer
t = Timer(5, app.httpd.shutdown)
t.start()
return "Server shut down"
Solution 16 - Python
For Windows, it is quite easy to stop/kill flask server -
- Goto Task Manager
- Find flask.exe
- Select and End process