進捗表示¶
Richは、長時間実行されるタスク(ファイルのコピーなど)の進捗状況に関する継続的に更新される情報を表示できます。表示される情報は設定可能で、デフォルトでは「タスク」の説明、プログレスバー、完了率、残り時間の推定が表示されます。
Richの進捗表示は、それぞれバーと進捗情報を持つ複数のタスクをサポートしています。スレッドまたはプロセスで作業が行われている並行タスクの追跡に使用できます。
進捗表示の外観を確認するには、コマンドラインから次のコマンドを実行してみてください。
python -m rich.progress
注記
ProgressはJupyter Notebookでも動作しますが、自動更新は無効化されている点に注意してください。refresh()
を明示的に呼び出すか、update()
を呼び出す際にrefresh=True
を設定する必要があります。または、各ループで自動的に更新を行う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オブジェクトを作成したら、add_task()
でタスクを追加し、update()
で進捗を更新します。
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)
タスクに関連付けられたtotal
値は、進捗が100%に達するまでに完了する必要があるステップの数です。このコンテキストでのステップとは、アプリケーションにとって意味のあるものなら何でも構いません。ファイルの読み取りバイト数、処理された画像の数などです。
タスクの更新¶
add_task()
を呼び出すと、タスクIDが返されます。このIDを使用して、作業が完了した場合、または情報が変更された場合にupdate()
を呼び出します。通常、ステップが完了するたびにcompleted
を更新する必要があります。completed
を直接更新するか、現在のcompleted
値に追加するadvance
を設定することでこれを行うことができます。
update()
メソッドは、タスクにも関連付けられたキーワード引数を収集します。これを使用して、進捗表示にレンダリングする追加情報を提供します。追加の引数はtask.fields
に格納され、列クラスで参照できます。
タスクの非表示¶
タスクのvisible
値を更新することで、タスクの表示/非表示を切り替えることができます。タスクはデフォルトで表示されますが、visible=False
でadd_task()
を呼び出すことによって非表示のタスクを追加することもできます。
一時的な進捗¶
通常、進捗コンテキストマネージャーを終了する場合(またはstop()
を呼び出す場合)、最後に更新された表示が、カーソルが次の行にある状態でターミナルに残ります。Progressコンストラクタでtransient=True
を設定することで、終了時に進捗表示を消去することもできます。例を以下に示します。
with Progress(transient=True) as progress:
task = progress.add_task("Working", total=100)
do_work(task)
一時的な進捗表示は、タスクが完了したときにターミナルの出力を最小限に抑えたい場合に役立ちます。
不定の進捗¶
タスクを追加すると、自動的に開始され、0%のプログレスバーが表示され、残り時間は現在時刻から計算されます。サーバーからの応答を待機したり、ディレクトリ内のファイルをカウントしたりするなど、進捗の更新を開始するまでに長い遅延がある場合は、うまく機能しない可能性があります(例)。このような場合は、start=False
またはtotal=None
でadd_task()
を呼び出すことができます。これにより、ユーザーに何かが動作中であることを知らせる脈打つアニメーションが表示されます。これは、不定プログレスバーと呼ばれます。ステップ数がわかったら、start_task()
を呼び出すと0%のプログレスバーが表示され、その後は通常どおりupdate()
を呼び出します。
自動更新¶
デフォルトでは、進捗情報は1秒間に10回更新されます。Progress
コンストラクタのrefresh_per_second
引数で更新頻度を設定できます。更新頻度がそれほど高くないことがわかっている場合は、これを10よりも低い値に設定する必要があります。
更新頻度が非常に低い場合は、自動更新を完全に無効にすることもできます。これを行うには、コンストラクタでauto_refresh=False
を設定します。自動更新を無効にした場合は、タスクを更新した後にrefresh()
を手動で呼び出す必要があります。
展開¶
プログレスバーは、タスク情報を表示するために必要なターミナルの幅のみを使用します。Progressコンストラクタでexpand
引数を設定すると、Richは進捗表示をすべての利用可能な幅に拡大します。
列¶
Progress
コンストラクタの位置引数を使用して、進捗表示の列をカスタマイズできます。列は、フォーマット文字列または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(),
)
デフォルトに加えて独自の列を持つProgressを作成するには、get_default_columns()
を使用します。
progress = Progress(
SpinnerColumn(),
*Progress.get_default_columns(),
TimeElapsedColumn(),
)
次の列オブジェクトを使用できます。
BarColumn
バーを表示します。TextColumn
テキストを表示します。TimeElapsedColumn
経過時間を表示します。TimeRemainingColumn
残り時間の推定値を表示します。MofNCompleteColumn
完了状況を"{task.completed}/{task.total}"
として表示します(完了数と総数が整数の場合に最適です)。FileSizeColumn
ファイルサイズとして進捗状況を表示します(ステップがバイト単位であることを前提としています)。TotalFileSizeColumn
ファイルの総サイズを表示します(ステップがバイト単位であることを前提としています)。DownloadColumn
ダウンロードの進捗状況を表示します(ステップがバイト単位であることを前提としています)。TransferSpeedColumn
転送速度を表示します(ステップがバイト単位であることを前提としています)。SpinnerColumn
「スピナー」アニメーションを表示します。RenderableColumn
カラムに任意のRichレンダラブルを表示します。
独自の列を実装するには、ProgressColumn
クラスを拡張し、他の列と同様に使用します。
テーブル列¶
Richは、Progressインスタンス内のタスクに対してTable
を構築します。このタスクテーブルの列の作成方法をカスタマイズするには、Columnコンストラクタのtable_column
引数を指定します。これはColumn
インスタンスである必要があります。
次の例は、説明がターミナル幅の3分の1を占め、バーが残りの3分の2を占めるプログレスバーを示しています。
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)
出力/ログ¶
Progressクラスは内部的にConsoleオブジェクトを作成し、progress.console
からアクセスできます。このコンソールに出力またはログを出力すると、出力は進捗表示の上に表示されます。例を以下に示します。
with Progress() as progress:
task = progress.add_task("twiddling thumbs", total=10)
for job in range(10):
progress.console.print(f"Working on job #{job}")
run_job(job)
progress.advance(task)
使用する別のConsoleオブジェクトがある場合は、Progress
コンストラクタに渡します。例を以下に示します。
from my_project import my_console
with Progress(console=my_console) as progress:
my_console.print("[bold blue]Starting work!")
do_work(progress)
stdout/stderrのリダイレクト¶
進捗表示の視覚的な表示を壊さないように、Richはstdout
とstderr
をリダイレクトします。これにより、組み込みのprint
文を使用できます。この機能はデフォルトで有効になっていますが、redirect_stdout
またはredirect_stderr
をFalse
に設定することで無効にできます。
カスタマイズ¶
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()
を呼び出すことができます。これは、プログレスバーを表示するようにファイルをラップするコンテキストマネージャーを返します。この関数を使用する場合は、読み取るバイト数または文字数を設定する必要があります。
これはインターネットから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
コマンドの最小限のクローンであるファイルコピー中にプログレスバーを表示するcp_progress.py <https://github.com/willmcgugan/rich/blob/master/examples/cp_progress.py>を参照してください。
複数のProgress¶
単一のProgressインスタンスでは、タスクごとに異なる列を持つことはできません。ただし、ライブ表示には、任意の数のProgressインスタンスを含めることができます。複数のProgressインスタンスの使用例については、live_progress.pyとdynamic_progress.pyを参照してください。
例¶
プログレス表示の現実的なアプリケーションについては、downloader.pyを参照してください。このスクリプトは、プログレスバー、転送速度、ファイルサイズを使用して、複数のファイルを同時にダウンロードできます。