I am running WSGIServer using gevent but I also want to run a background worker.
from gevent import monkey
from gevent.pywsgi import WSGIServer
from flask import Flask, request,Response
monkey.patch_all()
from threading import Thread
api = Flask(__name__)
my_queue=[1,2,3]
#api.route('/add', methods=['GET'])
def add():
my_queue.append(request.args.get('item'))
return Response("Added!", 200)
def worker(id):
while True:
print(f"{id}-working-{my_queue}")
if __name__ == '__main__':
server = WSGIServer(('0.0.0.0', 5001), api)
server_thread = Thread(target=server.start)
worker1_thread = Thread(target=worker,args=(1,))
worker2_thread = Thread(target=worker,args=(2,))
server_thread.start()
worker1_thread.start()
worker2_thread.start()
If I am running it without monkey.patch_all(), my two worker works in parallel but the API will not respond.
If I use monkey.patch_all() only the first worker will work and the API will also not respond.
How can I get this to work properly?
Also, I am aware I need a lock for the queue but I don't know how to implement it.
I am trying to figure out how to run my overloaded customized BaseHTTPServer instance in the background after running the "".serve_forever() method.
Normally when you run the method execution will hang until you execute a keyboard interrupt, but I would like it to serve requests in the background while continuing script execution. Please help!
You can start the server in a different thread: https://docs.python.org/3/library/_thread.html#thread.start_new_thread
So something like:
def start_server():
# Setup stuff here...
server.serve_forever()
# start the server in a background thread
thread.start_new_thread(start_server)
print('The server is running but my script is still executing!')
I was trying to do some long-term animation using async and thought I'd have to rewrite server to use aiohttp (https://docs.aiohttp.org/en/v0.12.0/web.html), but Olivers technique of using seperate thread saved me all that pain. My code looks like this, where MyHTTPServer is simply my custom sublass of HTTPServer
import threading
import asyncio
from http.server import BaseHTTPRequestHandler, HTTPServer
import socketserver
import io
import threading
async def tick_async(server):
while True:
server.animate_something()
await asyncio.sleep(1.0)
def start_server():
httpd.serve_forever()
try:
print('Server listening on port 8082...')
httpd = MyHTTPServer(('', 8082), MyHttpHandler)
asyncio.ensure_future(tick_async(httpd))
loop = asyncio.get_event_loop()
t = threading.Thread(target=start_server)
t.start()
loop.run_forever()
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.
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.
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.
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
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
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..."
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.
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)
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
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)
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)
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 on request.environ.get which is usable only inside web request's context (inside #app.route-ed function)
win32service's SvcStop method uses requests 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')
You can use method bellow
app.do_teardown_appcontext()
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.
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.
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"
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
If the port is known (e.g., 5000) a simple solution I have found is to enter:
fuser -k 5000/tcp
this will kill the process on port 5000.
How to kill a process running on particular port in Linux?
For Windows, it is quite easy to stop/kill flask server -
Goto Task Manager
Find flask.exe
Select and End process
I want to start a simple web server locally, then launch a browser with an url just served. This is something that I'd like to write,
from wsgiref.simple_server import make_server
import webbrowser
srv = make_server(...)
srv.blocking = False
srv.serve_forever()
webbrowser.open_new_tab(...)
try:
srv.blocking = True
except KeyboardInterrupt:
pass
print 'Bye'
The problem is, I couldn't find a way to set a blocking option for the wsgiref simple server. By default, it's blocking, so the browser would be launched only after I stopped it. If I launch the browser first, the request is not handled yet. I'd prefer to use a http server from the standard library, not an external one, like tornado.
You either have to spawn a thread with the server, so you can continue with your control flow, or you have to use 2 python processes.
untested code, you should get the idea
class ServerThread(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
def run(self):
srv = make_server(...)
srv.serve_forever()
if '__main__'==__name__:
ServerThread().start()
webbrowser.open_new_tab(...)
I have a class that I wish to test via SimpleXMLRPCServer in python. The way I have my unit test set up is that I create a new thread, and start SimpleXMLRPCServer in that. Then I run all the test, and finally shut down.
This is my ServerThread:
class ServerThread(Thread):
running = True
def run(self):
self.server = #Creates and starts SimpleXMLRPCServer
while (self.running):
self.server.handle_request()
def stop(self):
self.running = False
self.server.server_close()
The problem is, that calling ServerThread.stop(), followed by Thread.stop() and Thread.join() will not cause the thread to stop properly if it's already waiting for a request in handle_request. And since there doesn't seem to be any interrupt or timeout mechanisms here that I can use, I am at a loss for how I can cleanly shut down the server thread.
I had the same problem and after hours of research i solved it by switching from using my own handle_request() loop to serve_forever() to start the server.
serve_forever() starts an internal loop like yours. This loop can be stopped by calling shutdown(). After stopping the loop it is possible to stop the server with server_close().
I don't know why this works and the handle_request() loop don't, but it does ;P
Here is my code:
from threading import Thread
from xmlrpc.server import SimpleXMLRPCServer
from pyWebService.server.service.WebServiceRequestHandler import WebServiceRquestHandler
class WebServiceServer(Thread):
def __init__(self, ip, port):
super(WebServiceServer, self).__init__()
self.running = True
self.server = SimpleXMLRPCServer((ip, port),requestHandler=WebServiceRquestHandler)
self.server.register_introspection_functions()
def register_function(self, function):
self.server.register_function(function)
def run(self):
self.server.serve_forever()
def stop_server(self):
self.server.shutdown()
self.server.server_close()
print("starting server")
webService = WebServiceServer("localhost", 8010)
webService.start()
print("stopping server")
webService.stop_server()
webService.join()
print("server stopped")
Two suggestions.
Suggestion One is to use a separate process instead of a separate thread.
Create a stand-alone XMLRPC server program.
Start it with subprocess.Popen().
Kill it when the test is done. In standard OS's (not Windows) the kill works nicely. In Windows, however, there's no trivial kill function, but there are recipes for this.
The other suggestion is to have a function in your XMLRPC server which causes server self-destruction. You define a function that calls sys.exit() or os.abort() or raises a similar exception that will stop the process.
This is my way. send SIGTERM to self. (Works for me)
Server code
import os
import signal
import xmlrpc.server
server = xmlrpc.server.SimpleXMLRPCServer(("0.0.0.0", 8000))
server.register_function(lambda: os.kill(os.getpid(), signal.SIGTERM), 'quit')
server.serve_forever()
Client code
import xmlrpc.client
c = xmlrpc.client.ServerProxy("http://localhost:8000")
try:
c.quit()
except ConnectionRefusedError:
pass