一行上書きする場合
一行を上書きする場合、\r(キャリッジリターン)を使用します。これはカーソルを行の先頭に戻す制御文字です。
print("\r"+"一行を上書きします!",end="")
end=""を使用して改行を行わないようにします。
カウントダウンタイマーの例
\rの実践的な使い方として、カウントダウンタイマーを実装してみます。
import time
import sys
def countdown(seconds):
for i in range(seconds, 0, -1):
# \rで行頭に戻り、上書き表示
sys.stdout.write(f"\r残り {i:3d} 秒")
sys.stdout.flush()
time.sleep(1)
sys.stdout.write("\r完了! \n")
countdown(10)
ここでsys.stdout.writeとsys.stdout.flush()を使っています。printは内部的にsys.stdout.writeを呼び出しますが、sys.stdoutを直接使うことでバッファリングの制御がより明確になります。flush()を呼ぶことで、出力が即座に画面に反映されます。
注意点: 前回の出力より短い文字列を上書きすると、前の文字が残ってしまいます。上の例では"完了!"の後にスペースを入れて、前の表示を確実に消しています。
スピニングカーソルの実装
処理中であることを視覚的に示すスピニングカーソル(ローディングアニメーション)も\rで実装できます。
import sys
import time
import itertools
def spinning_cursor(duration=5):
spinner = itertools.cycle(['|', '/', '-', '\\'])
end_time = time.time() + duration
while time.time() < end_time:
sys.stdout.write(f"\r処理中... {next(spinner)}")
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write("\r処理完了! \n")
spinning_cursor(3)
itertools.cycleを使うことで、スピナー文字を無限に繰り返すことができます。
複数行を上書きする場合
複数行を上書きするような表示を行う場合、特殊なエスケープシーケンス\033[nA(カーソルをn行上に移動)などを利用します。
print("最初の行")
print("二番目の行")
# カーソルを1行上に移動し、上書き
print("\033[1A新しい二番目の行")
ANSIエスケープシーケンス一覧
ターミナル上のカーソル制御や装飾に使えるANSIエスケープシーケンスの主要なものを表にまとめます。
カーソル操作
| シーケンス | 説明 | 使用例 |
|---|---|---|
\033[nA | カーソルをn行上に移動 | print("\033[2A") |
\033[nB | カーソルをn行下に移動 | print("\033[1B") |
\033[nC | カーソルをn列右に移動 | print("\033[5C") |
\033[nD | カーソルをn列左に移動 | print("\033[3D") |
\033[2K | 現在の行をクリア | print("\033[2K", end="") |
\033[J | カーソル以降をクリア | print("\033[J", end="") |
\033[H | カーソルを画面左上に移動 | print("\033[H") |
\033[{r};{c}H | カーソルを行r, 列cに移動 | print("\033[5;10H") |
テキスト装飾(色・スタイル)
| シーケンス | 説明 |
|---|---|
\033[0m | リセット(装飾解除) |
\033[1m | 太字 |
\033[4m | 下線 |
\033[31m | 赤色テキスト |
\033[32m | 緑色テキスト |
\033[33m | 黄色テキスト |
\033[34m | 青色テキスト |
\033[41m | 赤色背景 |
\033[42m | 緑色背景 |
例えば、色付きのステータス表示は以下のように書けます。
# 成功時は緑、失敗時は赤で表示
def print_status(message, success=True):
color = "\033[32m" if success else "\033[31m"
reset = "\033[0m"
print(f"{color}{message}{reset}")
print_status("テスト通過", success=True)
print_status("テスト失敗", success=False)
ダウンロード進捗表示の実装例
\rとANSIエスケープシーケンスを組み合わせて、実用的なダウンロード進捗表示を実装してみます。
import sys
import time
def download_progress(total_size, chunk_size=1024):
"""ダウンロード進捗をプログレスバーで表示する"""
downloaded = 0
bar_length = 40
while downloaded < total_size:
downloaded += chunk_size
if downloaded > total_size:
downloaded = total_size
# 進捗率の計算
progress = downloaded / total_size
filled = int(bar_length * progress)
bar = "█" * filled + "░" * (bar_length - filled)
# MB単位で表示
dl_mb = downloaded / (1024 * 1024)
total_mb = total_size / (1024 * 1024)
# 色付きで進捗表示
if progress < 0.5:
color = "\033[33m" # 黄色
else:
color = "\033[32m" # 緑色
reset = "\033[0m"
sys.stdout.write(
f"\r{color}[{bar}]{reset} "
f"{progress:6.1%} "
f"({dl_mb:.1f}/{total_mb:.1f} MB)"
)
sys.stdout.flush()
time.sleep(0.01) # ダウンロードのシミュレーション
sys.stdout.write("\n")
print("ダウンロード完了!")
# 10MBのファイルをシミュレーション
download_progress(10 * 1024 * 1024, chunk_size=100 * 1024)
複数行リアルタイム更新の例
ANSIエスケープシーケンスを組み合わせると、複数のタスクの進捗を同時にリアルタイム更新できます。
import sys
import time
import random
def multi_task_progress():
"""複数タスクの進捗を同時更新する"""
tasks = ["データ取得", "前処理 ", "学習 ", "評価 "]
progress = [0] * len(tasks)
# 初期表示
for task in tasks:
print(f" {task}: [{'░' * 30}] 0%")
while not all(p >= 100 for p in progress):
# ランダムに進捗を更新
for i in range(len(tasks)):
if progress[i] < 100:
progress[i] = min(100, progress[i] + random.randint(0, 5))
# カーソルをタスク数分上に移動
sys.stdout.write(f"\033[{len(tasks)}A")
for i, task in enumerate(tasks):
filled = int(30 * progress[i] / 100)
bar = "█" * filled + "░" * (30 - filled)
if progress[i] >= 100:
color = "\033[32m" # 完了: 緑
else:
color = "\033[33m" # 進行中: 黄
reset = "\033[0m"
print(f" {task}: {color}[{bar}]{reset} {progress[i]:3d}%")
time.sleep(0.1)
multi_task_progress()
クロスプラットフォーム対応
ANSIエスケープシーケンスはLinuxやmacOSのターミナルではそのまま動作しますが、Windowsの従来のコマンドプロンプト(cmd.exe)では対応していません。
Windowsでの対応方法
Windows 10以降のWindows Terminalや PowerShellではANSIエスケープシーケンスがサポートされていますが、古い環境との互換性を保つにはcoloramaライブラリを使います。
# pip install colorama
from colorama import init, Fore, Style
# WindowsでANSIエスケープを有効化
init()
# coloramaを使った色付き出力
print(Fore.GREEN + "成功" + Style.RESET_ALL)
print(Fore.RED + "エラー" + Style.RESET_ALL)
colorama.init()を呼ぶだけで、WindowsでもANSIエスケープシーケンスが正しく動作するようになります。Linux/macOSでは何もしない(副作用がない)ため、クロスプラットフォームなコードに適しています。
os.nameによる分岐
coloramaを使わない場合は、os.nameで分岐する方法もあります。
import os
import sys
def supports_ansi():
"""ANSIエスケープシーケンスが使えるか判定"""
if os.name == "nt":
# Windows 10 build 10586以降はサポート
return os.environ.get("WT_SESSION") is not None # Windows Terminal
return hasattr(sys.stdout, "isatty") and sys.stdout.isatty()
if supports_ansi():
GREEN = "\033[32m"
RESET = "\033[0m"
else:
GREEN = ""
RESET = ""
print(f"{GREEN}ステータス: OK{RESET}")
ライブラリ比較:手動 vs tqdm vs rich
用途に応じて適切な方法を選びましょう。
| 特性 | 手動(\r / ANSI) | tqdm | rich |
|---|---|---|---|
| 外部依存 | なし | pip install | pip install |
| プログレスバー | 自作が必要 | 1行で実装可能 | 1行で実装可能 |
| 複数バー同時表示 | 自作が必要 | サポート | サポート |
| テーブル表示 | 不可 | 不可 | サポート |
| 色付き出力 | ANSIコード手動 | 限定的 | Rich Markup で簡単 |
| Windows対応 | colorama必要 | 自動対応 | 自動対応 |
| カスタマイズ性 | 完全に自由 | 中程度 | 高い |
| 学習コスト | 低い(原理理解向き) | 低い | 中程度 |
| 適したケース | 軽量な用途、学習目的 | ループ処理 | リッチなCLIアプリ |
シンプルな上書き表示には本記事の方法を、ループ処理のプログレスバーにはtqdmを、リッチなCLIアプリにはrichの利用を検討してください。
モダンなPython出力ライブラリ
printの上書き以外にも、リッチな出力を実現するライブラリがあります。
richライブラリ
richはターミナルに色付きテキスト、テーブル、プログレスバーなどを表示できるライブラリです。
from rich.console import Console
from rich.table import Table
console = Console()
# プログレス表示
from rich.progress import track
import time
for i in track(range(100), description="Processing..."):
time.sleep(0.01)
# ステータス表示(スピナー付き)
with console.status("Computing..."):
time.sleep(2)
console.print("[bold green]Done![/bold green]")
tqdmによるプログレスバー
tqdmは簡潔な記述でプログレスバーを表示できます。上書き表示の代替として広く使われています。
from tqdm import tqdm
import time
for i in tqdm(range(100)):
time.sleep(0.01)
関連記事
- Pythonでプログレスバーを自作する(tqdmなし) - この記事で紹介したキャリッジリターンやANSIエスケープシーケンスを活用して、プログレスバーを自作する方法を解説しています。
- PythonのMatplotlibで3Dアニメーション(GIF)を作成する方法 - Matplotlibを使ったリッチな出力・可視化の実践
- Python正規表現実践ガイド:reモジュールの基本からパフォーマンス最適化まで - Python標準ライブラリの実践的な活用法
関連ツール
- DevToolBox - 開発者向け無料ツール集 - JSON整形、正規表現テスターなど85種類以上の開発者向けツール
