flask - 为什么使用 gunicorn 运行时,线程在 Flask 应用程序中不起作用?
问题描述
当文件上传到我的烧瓶应用程序时,会生成一个线程 ID。这被前端用于稍后获取文件读取过程的进度详细信息(cert_details 路由)
cert_details 路由使用 tesseract、opencv 等从 PDF 读取数据。这是一个资源密集型过程,可能需要一段时间才能执行
在进程运行时,我希望能够使用进度更新前端(即读入多少文件)。因此,我创建了一个单独的线程,该线程的值“进度”在每次处理文件时都会增加。
该应用程序在没有 gunicorn 的情况下工作,即当 docker 命令是CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
如果我将其更改为使用 gunicorn CMD ["gunicorn","--timeout", “60", "--bind", "0.0.0.0:5000", "app:app"]
,则在文件读取过程完成之前进度条不会更新(这违背了进度条的目的)。
为什么线程不适用于 gunicorn?有没有我必须采取的替代方法,或者它是否与线程饥饿有关?
import threading
from flask import Flask, flash, request, redirect, url_for, jsonify, send_from_directory, send_file
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app)
class ExportingThread(threading.Thread):
def __init__(self):
self.progress = 0
super().__init__()
exporting_threads = {}
@app.route('/uploads', methods=['POST'])
def upload_file():
if request.method == 'POST':
if 'files[]' not in request.files:
return {'status':'File upload unsuccesful'}
files = request.files.getlist('files[]')
for file in files:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
else:
return {'status':'Non pdf file type uploaded'}
global thread_id
thread_id = random.randint(0, 10000)
return {'status':'sucessful'}
@app.route('/get_thread_id')
def get_thread():
global thread_id
return str(thread_id)
@app.route('/progress', methods=['POST'])
def progress():
data = request.json
thread_id = data['thread_id']
global exporting_threads
if thread_id in exporting_threads:
return str(exporting_threads[thread_id].progress)
else:
return '0'
@app.route('/cert_details', methods=['POST'])
def get_details():
data = request.json
if 'filenames' not in data:
return {'error':'filenames not found'}
else:
filenames =data['filenames']
details =[]
global exporting_threads
global thread_id
exporting_threads[thread_id] = ExportingThread()
exporting_threads[thread_id].start()
for file in filenames:
#this is the resource intensive process using ocr / opencv
details.append( get_certficate_details( UPLOAD_FOLDER_LOCATION + file, file ) )
exporting_threads[thread_id].progress += 1
return jsonify(file_details = details)
解决方案
推荐阅读
- android - 将活动添加到底部导航栏 - 尝试调用虚拟方法 'void com.google.android.material.bottomnavigation
- java - 在 Java 中比较两个对象与 int 和 string 参数
- javascript - 为什么我的可注入角度服务类没有按预期保存类变量?
- java - 编写 Classes 类然后实现它们
- javascript - 是否可以同时更改克隆和原始元素?- jQuery
- java - 在运行时将类从一个更改为另一个
- sql - 获取 Max(Amount) 和关联的类型
- reactjs - 在反应 js 中切换显示/隐藏 li 上的“活动”类
- avro - 使用 Kafka binder 重播 Spring Cloud Stream 中的死信队列中的消息
- c++ - 带有可变参数的 std::function 列表如何工作