如何在网页上制作pandas操作的进度条

2023-11-23

我已经在谷歌上搜索了一段时间,但无法找到一种方法来做到这一点。我有一个简单的 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?

我想要的最终结果是:

  1. 用户单击上传,从其文件系统中选择 CSV 文件
  2. 用户点击提交
  3. 进度条开始运行
  4. 一旦进度条达到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:

  • 我需要每次都将进度重置为0submit按钮被按下。我尝试了几个地方将其重置为 0 但尚未找到工作版本。这肯定与我对流的工作原理缺乏了解有关。现在只有当我刷新页面时它才会重置。
  • 如何处理并发请求(又称为 Redis 竞争条件)?如果多个用户同时发出请求,则每个用户的进度应该是独立的。我正在考虑随机给予job_id对于每个submit事件并使其成为 Redis 中的键。由于我不需要在每项工作完成后都需要该条目,因此我将在完成后删除该条目。

我觉得我缺少的部分是理解text/event-stream。感觉我已经接近可行的解决方案了。请分享您对执行此操作的“正确”方法的看法。我只是猜测并试图将一些适合我非常有限的理解的东西组合在一起。


好吧,我缩小了我遗漏的问题范围并解决了。我需要的概念包括

Backend

  • Redis作为键值数据库来存储可以通过端点查询的进度/progress for an 事件流 (HTML5)
  • 服务器发送事件 (SSE)用于传输进度:text/event-streamMIME 类型响应
  • Flask 应用程序中用于 SSE 的 Python 生成器
  • 将 Pandas 数据帧上的 for 循环的进度(正在处理的行索引)写入 Redis

Frontend

  • Open事件流:通过以下方式从客户端触发 SSEHTML 按钮
  • Close事件流:一旦事件数据达到 100%
  • 使用 jQuery 通过事件流动态更新进度条

示例 HTML

  <script>
  function getProgress() {
    var source = new EventSource("/progress");
    source.onmessage = function(event) {
      $('.progress-bar').css('width', event.data+'%').attr('aria-valuenow', event.data);
      $('.progress-bar-label').text(event.data+'%');

      // Event source closed after hitting 100%
      if(event.data == 100){
        source.close()
      }
    }
  }
  </script>

  <body>
    <div class="container">
      ...
      <form method="POST" action="/autoattr" enctype="multipart/form-data">
        <div class="form-group">
        ...
          <input type="file" name="file">
          <input type="submit" name="upload" onclick="getProgress()" />
        </div>
      </form>

      <div class="progress" style="width: 80%; margin: 50px;">
        <div class="progress-bar progress-bar-striped active"
          role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
          <span class="progress-bar-label">0%</span>
        </div>
      </div>
    </div>
  </body>

示例后端 Flask 代码

redis_host = "localhost"
redis_port = 6379
redis_password = ""
r = redis.StrictRedis(
  host=redis_host, port=redis_port, password=redis_password, decode_responses=True)

@app.route('/progress')
def progress():
  """Get percentage progress for auto attribute process"""
  r.set("progress", str(0))
  def progress_stream():
    p = int(r.get("progress"))
    while p < 100:
      p = int(r.get("progress"))
      p_msg = "data:" + str(p) + "\n\n"
      yield p_msg
      # Client closes EventSource on 100%, gets reopened when `submit` is pressed
      if p == 100:
        r.set("progress", str(0))
      time.sleep(1)

  return Response(progress_stream(), mimetype='text/event-stream')

剩下的就是 Pandas for 循环写入 Redis 的代码。

我通过几个小时的谷歌搜索拼凑了很多结果,所以我觉得最好在这里为那些也需要这个基本功能的人提供文档:在 Flask Web 应用程序中添加一个进度条以进行 Pandas 数据帧处理。

一些有用的参考

https://medium.com/code-zen/python-generator-and-html-server-sent-events-3cdf14140e56

https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9

什么是长轮询、Websockets、服务器发送事件 (SSE) 和 Comet?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在网页上制作pandas操作的进度条 的相关文章

随机推荐

  • .Select、.Activesheet、.Activecell 等...

    对于这个问题 我参考下面的帖子来澄清一下 为什么我的条件格式在用VBA添加时会偏移 在我这些天看到的很多很多帖子中 OP 被默默地允许使用 Activate Select Offset 等 而它们却为潜在错误 通常是由最终用户引起的 敞开了
  • 计算平均置信区间而不存储所有数据点

    对于大型n 请参阅下文了解如何确定足够大的值 根据中心极限定理 可以安全地将样本均值的分布视为正态 高斯 但我想要一个程序 为任何给出一个置信区间n 实现这一点的方法是使用 Student T 分布n 1自由程度 所以问题是 给定您一次收集
  • Ebean多对多查询

    我有两个类 用户和汽车 两者都有 ManyToMany 相互映射 User Entity public class User extends Model private int year ManyToMany cascade Cascade
  • 方法中变量的最大数量

    我在这里闲着 所以我有这个好奇心 有人可以告诉我 C 中每个方法的最大变量数是多少 我只是尝试编译生成的程序源 其中包含 26 26 26 26 个局部变量 而不是方法参数 它们被称为 aaaa aaab aaac等等 我遇到了这个限制 错
  • Hibernate 搜索与 spring-data-solr 、 spring-data-elasticsearch

    我有一个 Spring Boot Spring Data JPA hibernate Web 应用程序 想要引入文本搜索功能 我了解以下内容 hibernate search 或 spring data 都可以集成到我的应用程序中 Hibe
  • 如何从嵌套类访问超类方法?

    我希望这段代码可以解释这个问题 class Foo void a stuff class Bar extends Foo void a throw new Exception This is not allowed for Bar clas
  • 如何使用 div 和 css 模拟表格?

    像这样的表 table tr td td td td td td tr tr td td td td td td tr table 如何使用 div 和 css display table 规则创建一个 尝试这个 CSS table dis
  • 具有多个值列的数据透视表/交叉表

    我有一个产生以下结果集的视图 CREATE TABLE foo AS SELECT client id asset type current value future value FROM VALUES 1 0 10 20 1 1 5 10
  • 如何在编写测试时检查实际的 Laravel 命令输出?

    我正在为 Laravel Artisan 控制台命令编写一个非常基本的测试 如下所示 this gt artisan my command some option gt some value gt expectsOutput the exp
  • 如何在 Airflow 中运行异步函数?

    我正在编写一个气流任务来读取大型 csv 并将其保存到 postgresql 数据库 我发现这个 asyncpg 包具有复制功能 其运行速度比任何其他包都要快得多 然而 它是异步的 我不知道如何将它合并到Airflow中 这是示例代码 fr
  • 检查 W10 上的 Windows 版本

    有谁知道 TOSVersion Name 是否仍然适用于 Windows 10 我有一个 vcl 应用程序 它有一个表单显示事件 该事件获取操作系统详细信息并使用 SysUtils 中的 TOSVersion 记录将它们显示在 TMemo
  • 为什么 Java 会产生这么多进程?

    我编写了一个 Java 服务器应用程序 在Debian 7 虚拟服务器 该应用程序本身工作得很好 但我注意到一些非常奇怪的事情 Issue 打电话后java Xmx200M jar CCU jar我希望看到一个 Java 进程运行我的CCU
  • richfaces suggestBox 将附加值传递给支持 bean

    使用 RichFaces 时suggestionBox如何从带有文本输入的页面传递多个 id 或值suggestionBox支持豆 即 显示所选州内的建议城市列表 这是我的autoComplete method public List lt
  • pandas groupby 计算列中零的数量

    我有一个数据框 例如 Date B C 20 07 2018 10 8 20 07 2018 1 0 21 07 2018 0 1 21 07 2018 1 0 如何计算每个日期每列的零值和非零值 使用 sum 对我没有帮助 因为它会将非零
  • 从Python中的基类继承namedtuple

    是否有可能生产一个namedtuple哪个继承自基类 我想要的是Circle and Rectangle are namedtuples 和 都是从公共基类 Shape 继承的 from collections import namedtu
  • 如何将实体框架添加到控制台应用程序(包含图像)

    I try to add entity framework to console application I press add new item and then then 然后我添加了代码 class Program static vo
  • Chrome 不支持 Service Worker (69.0.3497.81)

    我开始使用 PWA 渐进式网络应用程序 当我尝试检查 Chrome 浏览器是否支持 Service Worker 时 它总是返回 false 下面的代码我用于检查 Note 我使用的是 chrome 版本 69 0 3497 81 官方版本
  • 如何使用 python nltk 获取解析树?

    给出以下句子 The old oak tree from India fell down 如何使用 python NLTK 获得句子的以下解析树表示 ROOT S NP NP DT The JJ old NN oak NN tree PP
  • char four[4] = "四";该语句的正确语义是什么?

    int main void char four 4 four return 0 当编译为 C 程序时 G 会报告 xxx cpp 在函数 int main 中 xxx cpp 3 错误 字符数组的初始化字符串太长 编译 C 程序时 GCC
  • 如何在网页上制作pandas操作的进度条

    我已经在谷歌上搜索了一段时间 但无法找到一种方法来做到这一点 我有一个简单的 Flask 应用程序 它接受 CSV 文件 将其读入 Pandas 数据帧 将其转换并输出为新的 CSV 文件 我已经成功上传并使用 HTML 转换它 div c