Start a flask application in separate thread
I'm currently developing a Python application on which I want to see real-time statistics. I wanted to use Flask
in order to make it easy to use and to understand.
The issue is that my Flask server should start at the very beginning of my Python application and stop at the very end. It should look like this:
def main():
""" My main application """
from watcher.flask import app
# watcher.flask define an app as in the Quickstart flask documentation.
# See: http://flask.pocoo.org/docs/0.10/quickstart/#quickstart
app.run() # Starting the flask application
do_my_stuff()
app.stop() # Undefined, for the idea
Because I need my application context (for the statistics), I can't use a multiprocessing.Process
. Then I was trying to use a threading.Thread
, but it looks like Werkzeug doesn't like it:
* Running on http://0.0.0.0:10079/
Exception in thread Flask Server:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File ".../develop-eggs/watcher.flask/src/watcher/flask/__init__.py", line 14, in _run
app.run(host=HOSTNAME, port=PORT, debug=DEBUG)
File ".../eggs/Flask-0.10.1-py2.7.egg/flask/app.py", line 772, in run
run_simple(host, port, self, **options)
File ".../eggs/Werkzeug-0.7-py2.7.egg/werkzeug/serving.py", line 609, in run_simple
run_with_reloader(inner, extra_files, reloader_interval)
File ".../eggs/Werkzeug-0.7-py2.7.egg/werkzeug/serving.py", line 524, in run_with_reloader
signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
ValueError: signal only works in main thread
How can I do that without running Flask in the main thread?
Solution 1:
You're running Flask
in debug mode, which enables the reloader (reloads the Flask server when your code changes).
Flask can run just fine in a separate thread, but the reloader expects to run in the main thread.
To solve your issue, you should either disable debug (app.debug = False
), or disable the reloader (app.use_reloader=False
).
Those can also be passed as arguments to app.run
: app.run(debug=True, use_reloader=False)
.
Solution 2:
Updated answer for Python 3 that's a bit simpler:
from flask import Flask
import threading
data = 'foo'
host_name = "0.0.0.0"
port = 23336
app = Flask(__name__)
@app.route("/")
def main():
return data
if __name__ == "__main__":
threading.Thread(target=lambda: app.run(host=host_name, port=port, debug=True, use_reloader=False)).start()