3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】長時間処理の「いつ終わるの?」問題を解決!プログレスバー実装を自作からライブラリまで3段階の備忘録

Posted at

はじめに

長時間かかる処理を実行するとき、「あとどのくらいで終わるの?」という不安を感じたことはありませんか?プログレスバーがあれば、進捗が一目でわかり、ユーザー体験が格段に向上します。

この記事では、プログレスバーを3つのレベルで実装し、それぞれの使い分けを備忘録します。

image.png


1. 10行で作るシンプルなプログレスバー

まずは仕組みを理解するため、最小限のコードでプログレスバーを作ってみましょう。

import time, sys
def progress_bar(total, current):
    progress = current / total
    filled = int(50 * progress)
    bar = '' * filled + '-' * (50 - filled)
    sys.stdout.write(f'\r[{bar}] {progress*100:.1f}%')
    sys.stdout.flush()

# デモ実行
print("シンプルなプログレスバー:")
for i in range(101):
    progress_bar(100, i)
    time.sleep(0.02)
print("\n✅ 完了!")

image.png

このコードは進捗率を視覚的に表示する基本的な仕組みを示しています。\rで行の先頭に戻り、sys.stdout.flush()で即座に表示を更新することで、動的な表示を実現しています。


2. 実用的なProgressBarクラス

次に、残り時間の予測機能を追加したクラスベースの実装を見てみましょう。

import time, sys
from datetime import timedelta

class ProgressBar:
    def __init__(self, total, desc="進捗"):
        self.total = total
        self.desc = desc
        self.current = 0
        self.start_time = time.time()
        
    def update(self, current):
        self.current = current
        progress = current / self.total
        filled = int(40 * progress)
        bar = '' * filled + '' * (40 - filled)
        
        elapsed = time.time() - self.start_time
        if current > 0:
            eta = int((elapsed / progress) - elapsed)
            eta_str = str(timedelta(seconds=eta))
        else:
            eta_str = "計算中"
            
        sys.stdout.write(f'\r{self.desc}: [{bar}] {progress*100:5.1f}% | '
                        f'残り: {eta_str}')
        sys.stdout.flush()
    
    def finish(self):
        self.update(self.total)
        print()

# デモ実行
print("時間予測付きプログレスバー:")
pbar = ProgressBar(80, "データ処理")
for i in range(81):
    pbar.update(i)
    time.sleep(0.05)
pbar.finish()

image.png

このクラスでは、経過時間と現在の進捗率から残り時間を計算し、ユーザーにより詳しい情報を提供します。中規模な処理で威力を発揮します。


3. tqdmでプロフェッショナルなプログレスバー

本格的な開発では、豊富な機能を持つtqdmライブラリを使用しましょう。

try:
    from tqdm import tqdm, trange
except ImportError:
    import subprocess, sys
    subprocess.check_call([sys.executable, "-m", "pip", "install", "tqdm"])
    from tqdm import tqdm, trange
import time

# 基本的な使い方
print("tqdm基本:")
for i in tqdm(range(60), desc="処理中"):
    time.sleep(0.03)

# ネストしたプログレスバー(機械学習風)
print("\n機械学習風ネストバー:")
for epoch in trange(3, desc="エポック"):
    for batch in trange(20, desc=f"エポック{epoch+1}", leave=False):
        time.sleep(0.03)

# リアルタイム情報表示
print("\nリアルタイム情報:")
with tqdm(range(50), desc="処理", unit="item") as pbar:
    for item in pbar:
        time.sleep(0.04)
        rate = pbar.format_dict.get('rate') or 0
        pbar.set_postfix({"": item, "速度": f"{rate:.1f}it/s"})

image.png

tqdmは機械学習のトレーニングループやデータ処理パイプラインなど、複雑な処理に最適です。ネストしたプログレスバーやリアルタイム情報表示など、高度な機能が簡単に利用できます。


まとめ

使い分け指針

用途 手法 特徴
学習用 自作関数 仕組み理解に最適
中規模処理 ProgressBarクラス 時間予測機能付き
本格開発 tqdm 高機能で安定した動作

実装のポイント

image.png

プログレスバーを効果的に活用するには、いくつかの重要なポイントがあります。まず更新頻度に注意が必要で、あまり頻繁に更新するとパフォーマンスが低下するため、適切な間隔での更新を心がけましょう。また、単純な進捗率だけでなく、残り時間や処理速度といった有用な情報も併せて表示することで、ユーザーの体験が大幅に向上します。さらに、例外が発生した場合でもプログレスバーを適切に終了させるエラー対応も忘れずに実装しておくことが大切です。
これらのポイントを押さえてプログレスバーを活用すれば、ユーザーにとって親しみやすく、使いやすいPythonアプリケーションを作ることができます!

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?