我已经在谷歌上搜索了一段时间,但无法找到一种方法来做到这一点。我有一个简单的 Flask 应用程序,它接受 CSV 文件,将其读入 Pandas 数据帧,将其转换并输出为新的 CSV 文件。我已经成功上传并使用 HTML 转换它
<div class="container">
<form method="POST" action="/convert" enctype="multipart/form-data">
<div class="form-group">
<br />
<input type="file" name="file">
<input type="submit" name="upload"/>
</div>
</form>
</div>
单击提交后,它会在后台运行转换一段时间,并在完成后自动触发下载。获取 result_df 并触发下载的代码如下所示
@app.route('/convert', methods=["POST"])
def convert(
if request.method == 'POST':
# Read uploaded file to df
input_csv_f = request.files['file']
input_df = pd.read_csv(input_csv_f)
# TODO: Add progress bar for pd_convert
result_df = pd_convert(input_df)
if result_df is not None:
resp = make_response(result_df.to_csv())
resp.headers["Content-Disposition"] = "attachment; filename=export.csv"
resp.headers["Content-Type"] = "text/csv"
return resp
我想添加一个进度条pd_convert
这本质上是一个 pandas apply 操作。我找到tqdm
现在与 pandas 一起工作,它有一个progress_apply
方法而不是apply
。但我不确定它是否与在网页上制作进度条相关。我想应该是这样,因为它可以在 Jupyter 笔记本上运行。如何添加进度条pd_convert()
here?
我想要的最终结果是:
- 用户单击上传,从其文件系统中选择 CSV 文件
- 用户点击提交
- 进度条开始运行
- 一旦进度条达到100%,就会触发下载
现在1和2已经完成了。那么接下来的问题就是如何触发下载。现在,我的convert
函数触发下载没有问题,因为响应是由文件构成的。如果我想渲染页面,我会做出响应return render_template(...)
。由于我只能得到一个响应,是否可以通过一次调用得到 3 和 4/convert
?
不是网络开发人员,仍在学习基础知识。提前致谢!
====编辑====
我尝试了这个例子here经过一些修改。我从数据帧的 for 循环中的行索引获取进度并将其放入 Redis 中。客户端通过询问这个新端点来从流中获取 Redis 的进度/progress
。就像是
@app.route('/progress')
def progress():
"""Get percentage progress for the dataframe process"""
r = redis.StrictRedis(
host=redis_host, port=redis_port, password=redis_password, decode_responses=True)
r.set("progress", str(0))
# TODO: Problem, 2nd submit doesn't clear progress to 0%. How to make independent progress for each client and clear to 0% on each submit
def get_progress():
p = int(r.get("progress"))
while p <= 100:
p = int(r.get("progress"))
p_msg = "data:" + str(p) + "\n\n"
yield p_msg
logging.info(p_msg)
if p == 100:
r.set("progress", str(0))
time.sleep(1)
return Response(get_progress(), mimetype='text/event-stream')
目前正在运行,但存在一些问题。原因肯定是我对这个解决方案缺乏理解。
Issues:
- 我需要每次都将进度重置为0
submit
按钮被按下。我尝试了几个地方将其重置为 0 但尚未找到工作版本。这肯定与我对流的工作原理缺乏了解有关。现在只有当我刷新页面时它才会重置。
- 如何处理并发请求(又称为 Redis 竞争条件)?如果多个用户同时发出请求,则每个用户的进度应该是独立的。我正在考虑随机给予
job_id
对于每个submit
事件并使其成为 Redis 中的键。由于我不需要在每项工作完成后都需要该条目,因此我将在完成后删除该条目。
我觉得我缺少的部分是理解text/event-stream
。感觉我已经接近可行的解决方案了。请分享您对执行此操作的“正确”方法的看法。我只是猜测并试图将一些适合我非常有限的理解的东西组合在一起。