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.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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.
Method 2
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.
Method 3
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
Method 4
My method can be proceeded via bash terminal/console
1) 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
Method 5
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..."
Method 6
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.
Method 7
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)
Method 8
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)
Method 9
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
Method 10
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
shutdownendpoint which can be used for graceful shutdown. Note: it relies onrequest.environ.getwhich is usable only inside web request’s context (inside@app.route-ed function) - win32service’s
SvcStopmethod usesrequeststo 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')
Method 11
You can use method bellow
app.do_teardown_appcontext()
Method 12
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)
Method 13
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.
Method 14
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'rn'
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.
Method 15
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"
Method 16
My bash script variant (LINUX):
#!/bin/bash
portFind="$1"
echo "Finding process on port: $portFind"
pid=$(netstat -tulnp | grep :"$1" | awk '{print $7}' | cut -f1 -d"/")
echo "Process found: $pid"
kill -9 $pid
echo "Process $pid killed"
Usage example:
sudo bash killWebServer.sh 2223
Output:
Finding process on port: 2223 Process found: 12706 Process 12706 killed
Method 17
For Windows, it is quite easy to stop/kill flask server –
- Goto Task Manager
- Find flask.exe
- Select and End process
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0