进度显示

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

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

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

python -m rich.progress

备注

Progress适用于Jupyter笔记本电脑,但需要注意的是,自动刷新功能被禁用。您需要显式调用 refresh() 或设置 refresh=True 当呼叫时 update() 。或使用 track() 在每个循环上自动执行刷新的功能。

基本用法

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

import time
from rich.progress import track

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

高级用法

如果需要在显示中显示多个任务,或者希望配置进度显示中的列,可以直接使用 Progress 班级。构建了Progress对象后,使用以下命令添加任务(S (add_task() ),并更新进度 update()

Progress类被设计为用作 context manager 这将自动启动和停止进度显示。

下面是一个简单的例子::

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)

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

正在更新任务

当你打电话的时候 add_task() 你会得到一个 Task ID 。使用此ID呼叫 update() 只要你完成了某项工作,或者任何信息发生了变化。通常,您将需要更新 completed 每次你完成了一个步骤。您可以通过设置 completed 直接或通过设置 advance 这将增加目前的 completed 价值。

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

隐藏任务

您可以通过更新任务来显示或隐藏任务 visible 价值。默认情况下,任务是可见的,但也可以通过调用 add_task() 使用 visible=False

暂时性进展

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

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

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

不确定的进展

添加任务时,它会自动 started 这意味着它将显示0%的进度条,剩余时间将从当前时间计算。如果在开始更新进度之前有很长的延迟,这可能不起作用;例如,您可能需要等待服务器的响应或对目录中的文件进行计数。在这些情况下,您可以调用 add_task() 使用 start=Falsetotal=None 它将显示一个脉冲动画,让用户知道有什么东西在工作。这就是众所周知的 indeterminate 进度条。当您有了可以调用的步骤数时 start_task() 它将以0%的速度显示进度条,然后 update() 像往常一样。

自动刷新

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

如果您的更新不是很频繁,您可能希望完全禁用自动刷新,这可以通过设置 auto_refresh=False 在构造函数上。如果禁用自动刷新,则需要调用 refresh() 更新您的任务后手动(S)。

展开

进度条(S)将只使用显示任务信息所需的终端宽度。如果您将 expand 参数,则Rich会将进度显示拉伸到最大可用宽度。

立柱

您可以使用位置参数自定义进度显示中的列 Progress 构造函数。这些列被指定为 format string 或者是 ProgressColumn 对象。

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

默认列相当于以下列:

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

要在默认列之外使用您自己的列创建进度,请使用 get_default_columns() **

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

以下列对象可用:

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

表列

里奇建立了一个 Table 用于Progress实例中的任务。您可以自定义此列的 tasks table 通过指定 table_column 参数,该参数应该是一个 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将重定向 stdoutstderr 这样您就可以使用内置的 print 陈述。默认情况下,此功能处于启用状态,但您可以通过设置 redirect_stdoutredirect_stderrFalse

自定义

如果 Progress 类并不能提供您在进度显示方面所需的内容,您可以重写 get_renderables 方法。例如,下面的类将呈现一个 Panel 在进度显示周围:

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提供了一种在读取文件时生成进度条的简单方法。如果你打电话给 open() 它将返回一个上下文管理器,在您阅读时显示一个进度条。当您不能轻松修改执行读取的代码时,这尤其有用。

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

import json
import rich.progress

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

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

下面是一个从Internet读取URL的示例::

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)

如果希望从多个文件中读取数据,可以使用 open()wrap_file() 若要将文件进度添加到现有的Progress实例,请执行以下操作。

看见 cp_progress.py 对于最小的克隆 cp 命令,该命令在复制文件时显示进度条。

多重进步

对于单个Progress实例,每个任务不能有不同的列。但是,您可以在 现场展示 。看见 live_progress.pydynamic_progress.py 有关使用多个Progress实例的示例。

示例

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