首页 > 解决方案 > 在烧瓶 api 中实际响应之前发送确认消息

问题描述

我正在做一个项目,客户端发送一些图像并基于这些图像生成一个 3D 网格,并在整个过程完成后返回“网格生成”消息。

目前,单个进程大约需要半个小时。并且执行时间会根据请求增加,因为生成网格软件一次只运行一次,所以其他请求必须等待执行。

我想向客户端发送一条消息,说明他们的图像已在网格创建后生成的实际响应之前上传,这样,用户不必等待太久而没有服务器端的任何响应。

我一直在研究简单的烧瓶 api 应用程序。以下是到目前为止的代码。

import os
import urllib.request
from flask import Flask, request, redirect, jsonify
from werkzeug.utils import secure_filename
from datetime import datetime
# import threading
from time import sleep
from flask_socketio import SocketIO, emit

UPLOAD_FOLDER = r'C:\Users\Pro-MechPC5\Desktop\ImageTest\Server\upload'

if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

app = Flask(__name__)
# socketio = SocketIO(app)

# @socketio.on('connect')                                                         
# def connect():                                                                  
#     emit('message', {'hello': "Hello"}) 
#app.secret_key = "secret key"
# app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/get_files', methods=['POST'])
def upload_file():
    info = dict(request.form.items())
    print(list(info.keys()))
    keys = list(info.keys())
    if 'meshname' not in keys:
        resp = jsonify({'message' : 'Please provide us your meshname.'})
        resp.status_code = 400
        return resp

    if 'email' not in keys:
        resp = jsonify({'message' : 'Please provide us your email id.'})
        resp.status_code = 400
        return resp

    # check if the post request has the file part
    if 'files[]' not in request.files:
        resp = jsonify({'message' : 'No file part in the request'})
        resp.status_code = 400
        return resp

    
    files = request.files.getlist('files[]')
    # datetime object containing current date and time
    now = datetime.now()
    # dd/mm/YY H:M:S
    email_id = info['email'].split('@')[0]
    sub_foldername = str(now.timestamp()) + '_' + info['meshname'] + '_' + email_id 
    print(sub_foldername)
    folder_name = UPLOAD_FOLDER + '\\' + sub_foldername
    

    if not os.path.exists(folder_name):
        os.makedirs(folder_name)

    print(folder_name)
    app.config['folder_name'] = folder_name
    errors = {}
    success = False
    
    for file in files:      
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['folder_name'], filename))
            success = True
        else:
            errors[file.filename] = 'File type is not allowed'
    
    if success and errors:
        errors['message'] = 'File(s) successfully uploaded'
        resp = jsonify(errors)
        resp.status_code = 500
        return resp
    if success:
        resp = jsonify({'message' : 'Files successfully uploaded'})
        resp.status_code = 201
        print()
        print("***************Starting MeshGen******************")
        # threading.Thread(target=create_mesh).start()
        #Send message (Images uploaded successfully, Mesh creation is in progress) here. 
        create_mesh()
        print()
        return resp
    else:
        resp = jsonify(errors)
        resp.status_code = 500
        return resp

def create_mesh():
    print("Started Task ....")
    # print(threading.current_thread().name)
    sleep(10)
    print('completed')

if __name__ == "__main__":
    app.run(debug=True)

我尝试通过将实际的网格创建作为后台任务运行并立即发送响应来使用线程。但是,它引起了一个问题,即当有多个请求时,它为网格生成创建了多个线程,这使得所有请求并行工作,因此,所有用户都必须等待几乎相同的时间,这是我不想要的。我想以先进先出的方式执行请求。

我研究了 celery、socketio 和烧瓶,但我找不到好的参考或正确理解这些库,因为我之前没有使用烧瓶及其库的经验。

那么,我怎么能在最终响应之前向客户端发送一些消息。或者,可以说,我如何在烧瓶中为单个请求发送多个响应。

或者如何为线程生成队列(最终选项,我认为这会更复杂),以便一次只运行一个线程。

标签: pythonmultithreadingflaskflask-socketio

解决方案


推荐阅读