在单独的线程中启动烧瓶应用程序

我目前正在开发一个 Python 应用程序,希望在其上查看实时统计数据。我想使用 Flask,以使其易于使用和理解。

问题是我的 Flask 服务器应该在 Python 应用程序的最开始启动,并在最后停止。它应该是这样的:

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

因为我需要我的应用程序上下文(为了统计数据) ,所以我不能使用 multiprocessing.Process。然后我试图使用 threading.Thread,但看起来沃克泽格不喜欢它:

 * 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

如果不在主线程中运行 Flask,我如何做到这一点?

72187 次浏览

From the werkzeug documentation:

Shutting Down The Server

New in version 0.7.

Starting with Werkzeug 0.7 the development server provides a way to shut down the server after a request. This currently only works with Python 2.6 and later and will only work with the development server. To initiate the shutdown you have to call a function named 'werkzeug.server.shutdown' in the WSGI environment:

def shutdown_server(environ):
if not 'werkzeug.server.shutdown' in environ:
raise RuntimeError('Not running the development server')
environ['werkzeug.server.shutdown']()

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).

If you are looking for accessing iPython terminal in Flask run your application in a separate thread. Try this example:

from flask import Flask
import thread


data = 'foo'
app = Flask(__name__)


@app.route("/")
def main():
return data


def flaskThread():
app.run()


if __name__ == "__main__":
thread.start_new_thread(flaskThread, ())

(Run this file in iPython)

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()

The original question was about how to run in a thread, and other answers address this, simply make sure to use_reloader=False. However graceful server shutdown when running in a thread I've still not found an answer to. One answer seems outdated as link to the current version of werkzeug shutting down the server suggests using a multiprocess.Process and calling terminate on that process.

I'm interested if anyone has a solution to graceful server shutdown when the flask app is running in a thread instead of a subprocess.