生产模式下运行Flask应用时如何终止无限循环
Flask应用uWSGI部署后无法停止后台循环的问题解决
问题场景
开发了一个带有Start和Stop按钮的Flask应用,核心需求:
- 点击Start按钮,程序持续打印
pStart(无限循环输出) - 点击Stop按钮,停止打印;再次点击Start可恢复打印
本地开发模式下功能正常,但使用uWSGI部署到生产环境后,Stop按钮无法终止打印循环,程序会一直输出pStart。
原始代码
Flask主程序(myproject.py)
from flask import Flask, render_template import sys flag1=True app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') @app.route('/start/') def start(): globals()['flag1']=True while flag1==True: print('pStart') return render_template('index.html') @app.route('/stop/') def stop(): globals()['flag1']=False return render_template('index.html') if __name__ == '__main__': app.run(host='0.0.0.0')
前端模板(templates/index.html)
<!doctype html> <head> <title>Test</title> <meta charset=utf-8> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> </head> <body> <h1>My Website</h1> <script type=text/javascript> $(function() { $('a#test').on('click', function(e) { e.preventDefault() $.getJSON('/start', function(data) { //do nothing }); document.getElementById('btn1').disabled = true; document.getElementById('btn2').disabled = false; return false; }); }); </script> <script type=text/javascript> $(function() { $('a#test1').on('click', function(e) { e.preventDefault() $.getJSON('/stop', function(data) { //do nothing }); document.getElementById('btn1').disabled = false; document.getElementById('btn2').disabled = true; return false; }); }); </script> <div class='container'> <form> <a href=# id=test><button id='btn1' class='btn btn-default'>Start</button></a> </form> </div> <p> <p> <div class='container'> <form> <a href=# id=test1><button id='btn2' class='btn btn-default' type="button" disabled>Stop</button></a> </form> </div> </body>
WSGI入口文件(wsgi.py)
from myproject import app if __name__ == "__main__": app.run()
原始uWSGI启动命令
uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app
问题根源
原始代码在/start/路由的请求处理线程中直接运行无限循环,阻塞了该线程的请求响应流程;同时uWSGI默认未启用多线程支持,导致后续的/stop/请求无法被及时处理,全局变量的修改也无法同步到被阻塞的线程,最终造成Stop按钮失效。
解决方法
通过引入线程分离后台任务与请求处理,并开启uWSGI的多线程支持,实现功能正常运行。
修改后的Flask代码
from flask import Flask, render_template import threading import time from werkzeug.serving import make_server import signal import sys app = Flask(__name__) threads = [] stop_flags = [] @app.route('/') def index(): return render_template('index.html') @app.route('/start/') def start(): stop_flags.append(False) thread = threading.Thread(target=run_loop, args=(len(stop_flags) - 1,)) threads.append(thread) thread.start() return render_template('index.html') @app.route('/stop/') def stop(): if stop_flags: stop_flags[-1] = True return render_template('index.html') def run_loop(thread_id): while not stop_flags[thread_id]: print('pStart') time.sleep(0.5) def signal_handler(signum, frame): for thread in threads: thread.join() server.shutdown() sys.exit(0) if __name__ == '__main__': signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGINT, signal_handler) server = make_server('0.0.0.0', 5000, app) server.serve_forever()
调整后的uWSGI启动命令
uwsgi --socket 0.0.0.0:5000 --protocol=http --enable-threads -w wsgi:app
关键改动说明
- 将无限循环任务放到独立线程中执行,避免阻塞Flask的请求响应主线程
- 添加
--enable-threads参数,让uWSGI支持多线程运行环境 - 使用列表存储每个线程的停止标志,确保线程间的状态同步可控
内容的提问来源于stack exchange,提问作者homievk
相关产品推荐
相关产品推荐

