首页 > 解决方案 > 与 Flask 应用程序一起运行代码

问题描述

我为我的 python 应用程序编写了一个 Web 界面。这在运行时运行良好,export FLASK_APP=main.py然后是flask run. 现在我希望实际的应用程序也能运行,这样界面就会很有用。

下面的代码是我的 main.py,我在其中调用了烧瓶应用程序工厂函数。

from webinterface import create_app

if __name__ == '__main__':
    create_app()
    while(True):
        # Some code logging different things

我想在无限循环中做一些事情,但是当我尝试运行应用程序时,它要么只运行 Web 界面,要么运行无限循环,这取决于我是否使用flask run或启动它python main.py

我怎样才能最好地做到这一点?

标签: pythonflask

解决方案


在前台应用程序的线程中运行 Flask 是可能的,有时也很方便。有一个技巧,一个大陷阱和一个约束。

限制是,这是您希望在“安全”环境中执行的操作(例如,在您的笔记本电脑上为本地浏览器提供服务器,或在您的家庭 Intranet 上),因为它涉及运行开发服务器,而您不这样做不想在充满敌意的环境中工作。您也不能使用自动页面重新加载(但您可以启用调试)。

陷阱在于,如果 UI 与前台应用程序共享任何重要的状态(包括字典),您将需要使用共享threading.Lock()来保护访问,以便一次只有一个线程在读取或写入数据。

诀窍是在创建应用程序之后但在启动它之前将对共享状态的引用注入到应用程序的配置中,执行以下操作:

def webserver(state):
    app.config['STATE'] = state
    # If running on, say, a Raspberry Pi, use 0.0.0.0 so that
    # you can connect to the web server from your intranet.
    app.run(host='0.0.0.0', use_reloader=False, debug=True)

def main():
    state = SharedState()
    web_thread = threading.Thread(target=webserver, args=(state,))
    web_thread.start()

    state.set('counter' 0)
    while True:
        # Do whatever you want in the foreground thread
        state.set('counter', state.get('counter') + 1)

class SharedState():
    def __init__(self):
        self.lock = threading.Lock()
        self.state = dict()

    def get(self, key):
        with self.lock:
            return self.state.get(key)

    def set(self, key, value):
        with self.lock:
            self.state[key] = value

然后,从 Flask 视图函数中,执行类似的操作

@app.route('/')
def home():
    state = app.config['STATE']
    counter = state.get(counter)
    return render_template("index.html", counter=counter)

推荐阅读