程序执行过程中多个用户并发执行耗时任务等时,为提高程序性能,这时可以使用异步处理技术来优化系统性能。常见的方法是将请求放到一个线程池或者进程池中进行管理。
以python自带的concurrent.futures库来实现异步处理任务。这个模块具有线程池和进程池、管理并行编程任务、处理非确定性的执行流程、进程或线程同步等功能。
示例代码1:
import time
from flask import Flask, request
from concurrent.futures import ThreadPoolExecutor
# app初始化
app = Flask(__name__)
# 同时处理的最大线程数,本示例中使用线程池,也可以使用进程池ProcessPoolExecutor,使用方法类似
executor = ThreadPoolExecutor(3)
@app.route("/postInfo", methods=["POST"])
def up_name():
"""
接收传递过来的信息
:return:
"""
data = {"data": "data"}
# 执行异步任务
executor.submit(do_job, data)
return data
def do_job(info):
"""
模拟异步任务
:param info:
:return:
"""
print(time.time(), "start:", info)
time.sleep(10)
print(time.time(), "end:", info)
if __name__ == '__main__':
app.run()
使用postman测试工具发起请求,代码中设置的最大异步数为3,本次在postman工具中同时执行请求5次看效果。
运行结果:
示例代码2:
import os
import time
from datetime import datetime
from flask import Flask, request
from werkzeug.utils import secure_filename
from concurrent.futures import ThreadPoolExecutor
# app初始化
app = Flask(__name__)
# 能接收的图片文件的大小
app.config['MAX_CONTENT_LENGTH'] = 2 * 1024 * 1024
# 同时处理的最大线程数,本示例中使用线程池,也可以使用进程池ProcessPoolExecutor,使用方法类似
executor = ThreadPoolExecutor(3)
# 能接收的文件后缀名
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])
# 允许接收的文件类型
def allow_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route("/uploadImageFile", methods=["POST"])
def upload_image_file():
"""
上传图片数据
:return:
"""
file = request.files['img']
if file and allow_file(file.filename):
filename = secure_filename(file.filename)
if not os.path.exists('temp'):
os.mkdir('temp')
file.save(os.path.join('temp', filename))
# 上传的文件是空文件
if os.stat(os.path.join('temp', filename)).st_size == 0:
os.remove(os.path.join('temp', filename))
return "Empty image file"
# 异步任务
executor.submit(do_job, filename)
return "POST Success"
else:
return "POST failed"
def do_job(filename):
"""
模拟异步任务
:param filename:
:return:
"""
print('{}-start do_job, file={}'.format(datetime.now(), filename))
time.sleep(10)
print('{}-finish do_job'.format(datetime.now()))
if __name__ == '__main__':
app.run()
postman测试:
运行结果: