进度显示

发布时间 2023-09-13 12:59:54作者: linux星

Rich 可以显示有关长时间运行的任务/文件副本等进度的持续更新信息。显示的信息是可配置的,默认将显示“任务”的描述、进度条、完成百分比和估计剩余时间。

丰富的进度显示支持多个任务,每个任务都有一个条形图和进度信息。您可以使用它来跟踪线程或进程中发生工作的并发任务。

要查看进度显示的外观,请从命令行尝试此操作:

python -m rich.progress

注意

进度适用于 Jupyter 笔记本,但需要注意的是自动刷新已禁用。调用 时需要显式调用或设置 。或者使用在每个循环中自动刷新的函数。refresh=True

基本用法

对于基本用法,请调用该函数,该函数接受序列(例如列表或范围对象)和您正在处理的作业的可选描述。跟踪函数将从序列中生成值,并更新每次迭代的进度信息。下面是一个示例:

import time
from rich.progress import track

for i in track(range(20), description="Processing..."):
    time.sleep(1)  # Simulate work being done

高级用法

如果您需要在显示中执行多个任务,或者希望在进度显示中配置列,则可以直接使用该类。构造进度对象后,使用 () 添加任务并使用 更新进度。

Progress 类旨在用作上下文管理器,该管理器将自动启动和停止进度显示。

下面是一个简单的示例:

import time

from rich.progress import Progress

with Progress() as progress:

    task1 = progress.add_task("[red]Downloading...", total=1000)
    task2 = progress.add_task("[green]Processing...", total=1000)
    task3 = progress.add_task("[cyan]Cooking...", total=1000)

    while not progress.finished:
        progress.update(task1, advance=0.5)
        progress.update(task2, advance=0.3)
        progress.update(task3, advance=0.9)
        time.sleep(0.02)

与任务关联的值是进度达到 100% 必须完成的步骤数。此上下文中的步骤是对应用程序有意义的任何步骤;它可以是读取的文件的字节数,或处理的图像数等。total

更新任务

当您调用时,您会得到一个任务 ID。使用此 ID 在完成某些工作或任何信息已更改时调用。通常,每次完成步骤时都需要更新。您可以通过直接更新或通过设置添加到当前值来执行此操作。completedcompletedadvancecompleted

该方法收集也与任务关联的关键字参数。使用此选项可提供要在进度显示中呈现的任何其他信息。其他参数存储在 Column 类中,并且可以在 Column 类中引用。task.fields

隐藏任务

您可以通过更新任务值来显示或隐藏任务。默认情况下,任务是可见的,但您也可以通过调用 来添加不可见的任务。visiblevisible=False

瞬态进度

通常,当您退出进度上下文管理器(或调用)时,上次刷新的显示仍保留在终端中,光标位于下一行。还可以通过在 Progress 构造函数上设置,使进度显示在退出时消失。下面是一个示例:transient=True

with Progress(transient=True) as progress:
    task = progress.add_task("Working", total=100)
    do_work(task)

如果您希望在任务完成时在终端中出现更多最小输出,则瞬态进度显示非常有用。

不确定进度

当您添加任务时,它会自动启动,这意味着它将在 0% 处显示进度条,剩余时间将从当前时间计算。如果在开始更新进度之前有很长的延迟,这可能效果不佳;例如,您可能需要等待来自服务器的响应或对目录中的文件进行计数。在这些情况下,您可以调用 或 将显示脉冲动画,让用户知道某些东西正在工作。这称为不确定进度条。当您有可以调用的步骤数时,它将以 0% 显示进度条,然后照常显示。start=Falsetotal=None

自动刷新

默认情况下,进度信息每秒将刷新 10 次。您可以使用构造函数上的参数设置刷新率。如果您知道更新不会那么频繁,则应将其设置为低于 10。refresh_per_second

如果更新不是很频繁,则可能需要完全禁用自动刷新,可以通过设置构造函数来实现。如果禁用自动刷新,则需要在更新任务后手动调用。auto_refresh=False

扩大

进度条将仅使用显示任务信息所需的终端宽度。如果在进度构造函数上设置参数,则 Rich 会将进度显示拉伸到完整的可用宽度。expand

您可以使用构造函数的位置参数自定义进度显示中的列。列被指定为格式字符串或对象。

格式字符串将使用单个值“task”呈现,该值将是一个实例。例如,将在列中显示任务描述,并显示已完成的总步骤数。通过关键字参数传递到 ~rich.progress.Progress.update 的其他字段存储在 中。您可以使用以下语法将它们添加到格式字符串中:."{task.description}""{task.completed} of {task.total}"task.fields"extra info: {task.fields[extra]}"

默认列等效于以下内容:

progress = Progress(
    TextColumn("[progress.description]{task.description}"),
    BarColumn(),
    TaskProgressColumn(),
    TimeRemainingColumn(),
)

要创建除默认值之外还包含您自己的列的进度,请使用 :

progress = Progress(
    SpinnerColumn(),
    *Progress.get_default_columns(),
    TimeElapsedColumn(),
)

可以使用以下列对象:

  • 显示栏。

  • 显示文本。

  • 显示经过的时间。

  • 显示估计的剩余时间。

  • 将完成进度显示为(如果已完成且总计为整数,则效果最佳)。"{task.completed}/{task.total}"

  • 将进度显示为文件大小(假设步骤为字节)。

  • 显示总文件大小(假设步骤为字节)。

  • 显示下载进度(假设步骤为字节)。

  • 显示传输速度(假设步骤为字节)。

  • 显示“微调器”动画。

  • 在列中显示任意丰富呈现对象。

若要实现自己的列,请扩展类并像使用其他列一样使用它。

表列

Rich 为进度实例中的任务构建 。可以通过在 Column 构造函数(应为实例)中指定参数来自定义创建此任务表的列的方式。table_column

以下示例演示了一个进度条,其中描述占据终端宽度的三分之一,条形占据剩余的三分之二:

from time import sleep

from rich.table import Column
from rich.progress import Progress, BarColumn, TextColumn

text_column = TextColumn("{task.description}", table_column=Column(ratio=1))
bar_column = BarColumn(bar_width=None, table_column=Column(ratio=2))
progress = Progress(text_column, bar_column, expand=True)

with progress:
    for n in progress.track(range(100)):
        progress.print(n)
        sleep(0.1)

重定向标准输出/标准输出

为了避免破坏进度显示视觉对象,Rich 将重定向,以便你可以使用内置语句。此功能默认处于启用状态,但您可以通过设置 或stdoutstderrprintredirect_stdoutredirect_stderrFalse

定制

如果类在进度显示方面没有提供您所需的确切内容,则可以重写该方法。例如,以下类将在进度显示周围呈现:

from rich.panel import Panel
from rich.progress import Progress

class MyProgress(Progress):
    def get_renderables(self):
        yield Panel(self.make_tasks_table(self.tasks))

从文件读取

Rich 提供了一种在读取文件时生成进度条的简单方法。如果你调用它将返回一个上下文管理器,该管理器在您阅读时显示进度条。当您无法轻松修改执行读取的代码时,这特别有用。

以下示例演示了在读取 JSON 文件时如何显示进度:

import json
import rich.progress

with rich.progress.open("data.json", "rb") as file:
    data = json.load(file)
print(data)

如果您已经有一个文件对象,则可以调用 WHAT 返回一个上下文管理器,该管理器包装您的文件,以便它显示进度条。如果使用此功能,则需要设置要读取的字节数或字符数。

下面是一个从互联网读取网址的示例:

from time import sleep
from urllib.request import urlopen

from rich.progress import wrap_file

response = urlopen("https://www.textualize.io")
size = int(response.headers["Content-Length"])

with wrap_file(response, size) as file:
    for line in file:
        print(line.decode("utf-8"), end="")
        sleep(0.1)

如果您希望从多个文件中读取数据,则可以使用文件进度或将文件进度添加到现有进度实例。

有关命令的最小克隆,请参阅cp_progress.py <https://github.com/willmcgugan/rich/blob/master/examples/cp_progress.py>,该克隆在复制文件时显示进度条。cp

多个进度

对于单个进度实例,每个任务不能具有不同的列。但是,您可以在实时显示中拥有任意数量的进度实例。有关使用多个进度实例的示例,请参阅 live_progress.py 和 dynamic_progress.py

有关进度显示的实际应用,请参阅 downloader.py。此脚本可以下载多个带有进度条、传输速度和文件大小的并发文件。