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

Fun*_*ayu 39 python multithreading flask

我正在开发一个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 
Run Code Online (Sandbox Code Playgroud)

因为我需要我的应用程序上下文(用于统计),我不能使用multiprocessing.Process.然后我试图使用a threading.Thread,但看起来Werkzeug不喜欢它:

 * 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
Run Code Online (Sandbox Code Playgroud)

如果不在主线程中运行Flask,我怎么能这样做呢?

Tho*_*zco 56

您正在Flask调试模式下运行,该模式启用重新加载(在代码更改时重新加载Flask服务器).

Flask可以在单独的线程中运行得很好,但是重新加载器期望在主线程中运行.


要解决您的问题,您应该禁用debug(app.debug = False),或禁用重新加载器(app.use_reloader=False).

那些也可以作为参数传递给app.run:app.run(debug=True, use_reloader=False).

  • @FunkySayu 通常你会创建一个 `/shutdown` 路由。路由代码执行:`flask.request.environ.get('werkzeug.server.shutdown')()`。要关闭服务器,您只需向 `/shutdown` 发出 HTTP 请求。为了安全起见,您通常会添加一个只有您的应用程序知道的令牌,以便其他人无法关闭服务器(并且您调用`/shutdown?token=somethingSecret`) (2认同)

Ras*_* Mv 12

如果您正在寻找访问烧瓶中的ipython终端,请在单独的线程中运行您的应用程序,请尝试以下示例: -

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 Code Online (Sandbox Code Playgroud)

在ipython中运行此文件


ske*_*r88 6

更新了Python 3的答案,方法更简单:

from flask import Flask                                                         
import threading

data = 'foo'
app = Flask(__name__)

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

if __name__ == "__main__":
    threading.Thread(target=app.run).start()
Run Code Online (Sandbox Code Playgroud)