GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

tqdm

tqdm – PythonとCLIの高速で拡張できるプログレスバー

投稿日:2018年4月8日 更新日:

PythonとCLIの高速で拡張できるプログレスバーhttps://pypi.python.org/pypi/tqdm

 

 

tqdm

 

 

 

tqdmはアラビア語で「progress」を意味し、スペイン語では「I love you so much」の略語を意味します。

簡単に、あなたのプログラムのループにスマートな進捗状況を表示させることができます。tqdm(iterable)をラップするだけです!

from tqdm import tqdm
for i in tqdm(range(10000)):
    ...

76%|████████████████████████████ | 7568/10000 [00:33<00:10, 229.00it/s]

trange(N)は、 tqdm(xrange(N))のショートカットとして使用できます。

REPL: ptpython

パイプでモジュールとして実行することもできます:

$ seq 9999999 | tqdm --unit_scale | wc -l
10.0Mit [00:02, 3.58Mit/s]
9999999
$ 7z a -bd -r backup.7z docs/ | grep Compressing | \
    tqdm --total $(find docs/ -type f | wc -l) --unit files >> backup.log
100%|███████████████████████████████▉| 8014/8014 [01:37<00:00, 82.29files/s]

 

オーバーヘッドは小さく、1ループ毎に約60ns(tqdm_guiでtqdm_gui )であり、パフォーマンスの回帰に対してユニットテストされています。 これと比較して、ProgressBarのオーバーヘッドは800ns / iterです。

低オーバーヘッドに加えて、 tqdmはスマート・アルゴリズムを使用して残りの時間を予測し、不要な反復表示をスキップします。大抵のケースで、オーバーヘッドは無視できます。

tqdmは、任意のプラットフォーム(Linux、Windows、Mac、FreeBSD、NetBSD、Solaris / SunOS)、任意のコンソールまたはGUI上で動作し、IPython / Jupyterノートブックとも親和性があります。

tqdmは依存関係( cursesなくても)は必要ありません。ちょうどPythonとcarriage return \rline feed \n制御文字をサポートする環境です。


 

インストール

 

最新のPyPI安定版

 

pip install tqdm

 

GitHubの最新開発リリース

 

現在のディレクトリにプルしてインストールします。

pip install -e git+https://github.com/tqdm/tqdm.git@master#egg=tqdm

 

Condaの最新リリース

 

conda install -c conda-forge tqdm

 

変更ログ

すべての変更のリストはGitHubのリリースで利用できます: wiki上allmychanges.comのようなクローラで。

 

使用法

tqdmは非常に汎用性があり、さまざまな方法で使用できます。 3つの主なものを以下に示します。

 

反復可能ベース

tqdm()を繰り返し可能にする:

text = ""
for char in tqdm(["a", "b", "c", "d"]):
    text = text + char

trange(i)は、 tqdm(range(i))特別に最適化されたインスタンスです。

for i in trange(100):
    pass

ループの外部でインスタンス化すると、 tqdm()を手動で制御できます。

pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
    pbar.set_description("Processing %s" % char)

 

マニュアル

with文を使用してtqdm()手動で制御する:

with tqdm(total=100) as pbar:
    for i in range(10):
        pbar.update(10)

オプションの変数total (またはlen()繰り返し可能)が提供されている場合、予測統計が表示されます。

また、変数にtqdm()を代入することもできますが、この場合は最後にdelまたはclose()を忘れないでください:

pbar = tqdm(total=100)
for i in range(10):
    pbar.update(10)
pbar.close()

 

モジュール

おそらく、 tqdm最も素晴らしい使い方は、スクリプトやコマンドラインにあります。 パイプ間にtqdm (またはpython -m tqdm )を挿入するだけで、すべてのstdinstdout渡され、 stderr進行状況が表示されます。

以下の例では、現在のディレクトリ内のすべてのPythonファイルの行数をカウントし、タイミング情報を示しています。

$ time find . -name '*.py' -exec cat \{} \; | wc -l
857365

real    0m3.458s
user    0m0.274s
sys     0m3.325s

$ time find . -name '*.py' -exec cat \{} \; | tqdm | wc -l
857366it [00:03, 246471.31it/s]
857365

real    0m3.585s
user    0m0.862s
sys     0m3.358s

tqdmの通常の引数も指定できることに注意してください。

$ find . -name '*.py' -exec cat \{} \; |
    tqdm --unit loc --unit_scale --total 857366 >> /dev/null
100%|███████████████████████████████████| 857K/857K [00:04<00:00, 246Kloc/s]

大きなディレクトリをバックアップしますか?

$ 7z a -bd -r backup.7z docs/ | grep Compressing |
    tqdm --total $(find docs/ -type f | wc -l) --unit files >> backup.log
100%|███████████████████████████████▉| 8014/8014 [01:37<00:00, 82.29files/s]

 

FAQと既知の問題

 

最も一般的な問題は、きれいな1行のプログレスバーではなく、複数行の過剰出力に関するものです。

  • 一般的なコンソール:キャリッジリターン( CR\r )のサポートが必要です。
  • ネストされた進行状況バー:
    • 一般的なコンソール:カーソルを前の行まで移動するためのサポートが必要です。 たとえば、 IDLEConEmu 、およびPyCharmここここ 、およびここでも )は完全にサポートされていません。
    • Windows:さらに、ネストされたバーがそれぞれのcoloramaように、Pythonモジュールのcoloramaが必要になることがあります。
  • Unicode:
    • ユニコードをサポートしていると報告している環境では、スムーズな進捗バーがあります。 フォールバックはASCIIのみのバーです。
    • Windowsコンソールは、しばしばUnicodeを部分的にしかサポートしていないため、明示的なascii = Trueここでも同様) が必要なことがよくあります。 これは、通常の幅のUnicode文字が「ワイド」として間違って表示されるか、またはレンダリングされないUnicode文字のためです。
  • 列挙されたiterablesのラッピング: enumerate(tqdm(...))代わりにenumerate(tqdm(...))使用しenumerate(tqdm(...)) numpy.ndenumerateも同様numpy.ndenumerate これは、列挙関数が反復可能変数の長さを隠す傾向があるためです。 tqdmはありません。
  • 圧縮されたiterablesのラップは、内部の最適化のために同様の問題があります。 tqdm(zip(a, b))は、 zip(tqdm(a), b)またはzip(tqdm(a), tqdm(b))ます。

他の困難に遭遇した場合は、

 

ドキュメンテーション

(2016年5月19日以降)

class tqdm(object):
  """
  Decorate an iterable object, returning an iterator which acts exactly
  like the original iterable, but prints a dynamically updating
  progressbar every time a value is requested.
  """

  def __init__(self, iterable=None, desc=None, total=None, leave=True,
               file=None, ncols=None, mininterval=0.1,
               maxinterval=10.0, miniters=None, ascii=None, disable=False,
               unit='it', unit_scale=False, dynamic_ncols=False,
               smoothing=0.3, bar_format=None, initial=0, position=None,
               postfix=None):

 

パラメーター

  • iterable:オプション、iterable
    プログレスバーで飾るために反復可能。 手動で更新を管理する場合は、空白のままにします。
  • desc:str、オプション
    プログレスバーのプレフィックス。
  • total:int、optional
    予想される反復回数。 (デフォルト:なし)可能であれば、len(iterable)が使用されます。 最後の手段として、基本進捗統計のみが表示されます(ETAなし、プログレスバーなし)。 guiがTrueで、このパラメータを後で更新する必要がある場合は、初期の任意の大きな正の整数、たとえばint(9e9)を指定します。
  • 離れる:bool、オプション
    [default:True]の場合、反復の終了時にプログレスバーのすべてのトレースを保持します。
  • ファイル: io.TextIOWrapperまたはio.StringIO 、オプション
    進捗メッセージを出力する場所を指定します(デフォルト:sys.stderr)。 file.write(str)およびfile.flush()メソッドを使用します。
  • ncols:int、optional
    出力メッセージ全体の幅。 指定されている場合は、プログレスバーのサイズを動的に変更してこの範囲内に留まります。 指定されていない場合、環境幅を使用しようとします。 フォールバックは10メートルの幅で、カウンタと統計の制限はありません。 0の場合、メーターは印刷されません(統計のみ)。
  • mininterval:オプションのfloat
    最小進捗表示更新間隔(秒単位)[デフォルト:0.1]
  • maxinterval:float、optional
    最大進捗表示更新間隔(秒)[デフォルト:10] 長い表示更新の遅れがminitersした場合にminitersに対応するminitersを自動的に調整します。 dynamic_minitersまたはモニタスレッドが有効な場合にのみ動作します。
  • miniters:int、optional
    最小進捗表示更新間隔(反復回数)。 0とdynamic_minitersが自動的に等しいmininterval調整されます(より多くのCPUが効率的で、タイトなループに適しています)。 0より大きい場合、指定された反復数の表示をスキップします。 非常に効率的なループを得るために、これとminintervalを微調整してください。 あなたの進歩が、高速反復と低速反復(ネットワーク、スキップ項目など)の両方で不安定である場合、miniters = 1を設定する必要があります。
  • ascii:ブール、オプション
    未指定またはFalseの場合は、ユニコード(平滑ブロック)を使用してメーターを塗りつぶします。 フォールバックは、ASCII文字1-9 #を使用することです。
  • 無効:bool、オプション
    プログレスバーラッパー全体を無効にするかどうかを指定します(デフォルト:False)。
  • ユニット:str、オプション
    各反復の単位を定義するために使用される文字列です(デフォルト:it)。
  • unit_scale:boolまたはintまたはfloat、オプション
    1またはTrueの場合、反復回数は自動的に縮小/スケーリングされ、国際単位系に従うメトリクスプレフィックス(キロ、メガなど)が追加されます[デフォルト:False]。 ゼロ以外の数であれば、totalとnをスケールします。
  • dynamic_ncols:bool、オプション
    設定されている場合は、常にncolsを環境に変更しncols (ウィンドウのサイズ変更を許可します)[デフォルト:False]。
  • 平滑化:浮動小数点、オプション
    速度推定値の指数移動平均平滑化係数(GUIモードでは無視されます)。 0(平均速度)から1(現在/瞬時速度)の範囲です(デフォルト:0.3)。
  • bar_format:str、オプション
    カスタムバーストリングの書式を指定します。 パフォーマンスに影響を与えることがあります。 [デフォルト: ‘{l_bar} {bar} {r_bar}’]、l_bar = ‘{desc}:{percentage:3.0f}%|’ とr_bar = ‘| 可能な値:l_bar、bar、r_bar、n、n_fmt、total、total_fmt、percentage、rate、rate_fmt、rate_noinv {n_fmt} / {total_fmt} / {total_fmt} 、rate_noinv_fmt、rate_inv、rate_inv_fmt、経過、残り、desc、後置。 末尾の “:”は、{desc}が空の場合は自動的に削除されます。
  • initial:int、optional
    初期カウンタ値。 プログレスバーを再起動するときに便利です(デフォルト:0)。
  • position:int、optional
    このバーを印刷する行オフセットを指定します(0から開始)。指定されていない場合は自動です。 一度に複数のバーを管理するのに便利です(例:スレッドから)。
  • 後置:dict、オプション
    バーの最後に表示する追加の統計を指定します。 注意:postfixは文字列ではなく、このメソッドのdict({‘key’:value}ペア)です。
  • unit_divisor:float、optional
    [default:1000]、unit_scaleがTrueでなければ無視されます。

 

Extra CLIオプション

  • delim:chr、オプション
    区切り文字[デフォルト: ‘n’]。 NULLには ‘0’を使用します。 注:Windowsシステムでは、Pythonは ‘n’を ‘rn’に変換します。
  • buf_size:int、オプション
    delimが指定されたときに使用される文字列バッファサイズ(バイト単位)[デフォルト:256]。
  • バイト:bool、オプション
    trueの場合、バイト数がカウントされ、 delim無視されます。

 

Returns

  • out:装飾されたイテレータ。
  def update(self, n=1):
      """
      Manually update the progress bar, useful for streams
      such as reading files.
      E.g.:
      >>> t = tqdm(total=filesize) # Initialise
      >>> for current_buffer in stream:
      ...    ...
      ...    t.update(len(current_buffer))
      >>> t.close()
      The last line is highly recommended, but possibly not necessary if
      ``t.update()`` will be called in such a way that ``filesize`` will be
      exactly reached and printed.

      Parameters
      ----------
      n  : int, optional
          Increment to add to the internal counter of iterations
          [default: 1].
      """

  def close(self):
      """
      Cleanup and (if leave=False) close the progressbar.
      """

  def unpause(self):
      """
      Restart tqdm timer from last print time.
      """

  def clear(self, nomove=False):
      """
      Clear current bar display
      """

  def refresh(self):
      """
      Force refresh the display of this bar
      """

  def write(cls, s, file=sys.stdout, end="\n"):
      """
      Print a message via tqdm (without overlap with bars)
      """

  def set_description(self, desc=None, refresh=True):
      """
      Set/modify description of the progress bar.

      Parameters
      ----------
      desc  : str, optional
      refresh  : bool, optional
          Forces refresh [default: True].
      """

  def set_postfix(self, ordered_dict=None, refresh=True, **kwargs):
      """
      Set/modify postfix (additional stats)
      with automatic formatting based on datatype.

      Parameters
      ----------
      refresh  : bool, optional
          Forces refresh [default: True].
      """

def trange(*args, **kwargs):
    """
    A shortcut for tqdm(xrange(*args), **kwargs).
    On Python3+ range is used instead of xrange.
    """

class tqdm_gui(tqdm):
    """
    Experimental GUI version of tqdm!
    """

def tgrange(*args, **kwargs):
    """
    Experimental GUI version of trange!
    """

class tqdm_notebook(tqdm):
    """
    Experimental IPython/Jupyter Notebook widget using tqdm!
    """

def tnrange(*args, **kwargs):
    """
    Experimental IPython/Jupyter Notebook widget using tqdm!
    """

 

例、高度な使用法

  • examplesフォルダを参照してください。
  • モジュールをインポートしてhelp()を実行help()か、
  • wikiに相談してください。

 

説明、追加の統計

カスタム情報は、 tqdmバーでdescpostfix引数を使用して動的に表示および更新できます。

from tqdm import trange
from random import random, randint
from time import sleep

t = trange(100)
for i in t:
    # Description will be displayed on the left
    t.set_description('GEN %i' % i)
    # Postfix will be displayed on the right, and will format automatically
    # based on argument's datatype
    t.set_postfix(loss=random(), gen=randint(1,999), str='h', lst=[1, 2])
    sleep(0.1)

 

ネストされた進行状況バー

tqdmは、ネストされた進行状況バーをサポートします。 ここに例があります:

from tqdm import trange
from time import sleep

for i in trange(10, desc='1st loop'):
    for j in trange(5, desc='2nd loop', leave=False):
        for k in trange(100, desc='3nd loop'):
            sleep(0.01)

Windowsでは、それぞれの行にネストされたバーを保持するために使用可能な場合、 coloramaが使用されます。

位置を手動で制御する(例えば、マルチスレッド使用の場合)には、 position=n指定できます。最も外側のバーではn=0 、次のバーではn=1などとなります。

from time import sleep
from tqdm import trange
from multiprocessing import Pool, freeze_support, RLock

L = list(range(9))

def progresser(n):
    interval = 0.001 / (n + 2)
    total = 5000
    text = "#{}, est. {:<04.2}s".format(n, interval * total)
    for i in trange(total, desc=text, position=n):
        sleep(interval)

if __name__ == '__main__':
    freeze_support()  # for Windows support
    p = Pool(len(L),
             # again, for Windows support
             initializer=tqdm.set_lock, initargs=(RLock(),))
    p.map(progresser, L)
    print("\n" * (len(L) - 2))

 

フックとコールバック

tqdmはコールバック/フックと手動更新を簡単にサポートできます。 urllib例をurllibます。

urllib.urlretrieveのドキュメント

[…]
存在する場合、フック関数は一度呼び出されます
ネットワーク接続の確立時および各ブロック読み出し後に1回
その後。 フックには3つの引数が渡されます。 ブロック数
これまでに転送されたブロックサイズ、バイト単位のブロックサイズ、およびファイルの合計サイズです。
[…]
import urllib, os
from tqdm import tqdm

class TqdmUpTo(tqdm):
    """Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
    def update_to(self, b=1, bsize=1, tsize=None):
        """
        b  : int, optional
            Number of blocks transferred so far [default: 1].
        bsize  : int, optional
            Size of each block (in tqdm units) [default: 1].
        tsize  : int, optional
            Total size (in tqdm units). If [default: None] remains unchanged.
        """
        if tsize is not None:
            self.total = tsize
        self.update(b * bsize - self.n)  # will also set self.n = b * bsize

eg_link = "https://caspersci.uk.to/matryoshka.zip"
with TqdmUpTo(unit='B', unit_scale=True, miniters=1,
              desc=eg_link.split('/')[-1]) as t:  # all optional kwargs
    urllib.urlretrieve(eg_link, filename=os.devnull,
                       reporthook=t.update_to, data=None)

ツイン#242からインスパイアされています。 examples / tqdm_wget.pyの機能代替。

潜在的に大きな反復速度の違いがあるときはいつでもminiters=1を使用することが推奨されます(パッチのついた接続でファイルをダウンロードするなど)。

 

パンダの統合

一般的な需要のために、我々はDataFrame.progress_applyのサポートを追加しました – ここにDataFrame.progress_applyDataFrameGroupBy.progress_apply例がありDataFrameGroupBy.progress_apply

import pandas as pd
import numpy as np
from tqdm import tqdm

df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))

# Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
# (can use `tqdm_gui`, `tqdm_notebook`, optional kwargs, etc.)
tqdm.pandas(desc="my bar!")

# Now you can use `progress_apply` instead of `apply`
# and `progress_map` instead of `map`
df.progress_apply(lambda x: x**2)
# can also groupby:
# df.groupby(0).progress_apply(lambda x: x**2)

これがどのように機能するか(独自のコールバックを変更する方法)に興味がある場合は、 examplesフォルダを参照するか、モジュールをインポートしてhelp()を実行しhelp()

 

IPython / Jupyter統合

IPython / Jupyterは、 tqdm_notebookサブモジュールを介してサポートされていtqdm_notebook

from tqdm import tnrange, tqdm_notebook
from time import sleep

for i in tnrange(10, desc='1st loop'):
    for j in tqdm_notebook(xrange(100), desc='2nd loop'):
        sleep(0.01)

サブモジュールは、 tqdm機能に加えてネイティブのJupyterウィジェット(IPython v1-v4およびJupyterと互換性があります)、ネストされたバーとカラーヒント(青:正常、緑:完了、赤:エラー/割り込み、ライトブルー:いいえETA); 以下に示すように。

 

 

メッセージを書く

tqdmは単純な印刷機構を使ってプログレスバーを表示するので、プログレスバーが開いている間はprint()を使って端末にメッセージを書き込まないでください。

tqdm barの表示との衝突なしに端末にメッセージを書き込むには、 .write()メソッドが用意されています。

from tqdm import tqdm, trange
from time import sleep

bar = trange(10)
for i in bar:
    # Print using tqdm class method .write()
    sleep(0.1)
    if not (i % 3):
        tqdm.write("Done task %i" % i)
    # Can also use bar.write()

デフォルトでは、これは標準出力sys.stdout出力されます。 file引数を使用してfileオブジェクトを指定できます。 たとえば、これを使用して、メッセージをログファイルまたはクラスにリダイレクトすることができます。

 

書き込みのリダイレクト

コンソールにメッセージを出力できるライブラリを使用している場合は、 print()tqdm.write()置き換えてライブラリを編集することは望ましくないかもしれません。 その場合、 sys.stdouttqdm.write()リダイレクトすることはオプションです。

sys.stdoutをリダイレクトするには、 tqdm.write()入力文字列を書き込むfile-likeクラスを作成し、引数file=sys.stdout, dynamic_ncols=True指定しfile=sys.stdout, dynamic_ncols=True

再利用可能な標準的な例を以下に示します。

from time import sleep
import contextlib
import sys
from tqdm import tqdm

class DummyTqdmFile(object):
    """Dummy file-like that will write to tqdm"""
    file = None
    def __init__(self, file):
        self.file = file

    def write(self, x):
        # Avoid print() second call (useless \n)
        if len(x.rstrip()) > 0:
            tqdm.write(x, file=self.file)

    def flush(self):
        return getattr(self.file, "flush", lambda: None)()

@contextlib.contextmanager
def std_out_err_redirect_tqdm():
    orig_out_err = sys.stdout, sys.stderr
    try:
        sys.stdout, sys.stderr = map(DummyTqdmFile, orig_out_err)
        yield orig_out_err[0]
    # Relay exceptions
    except Exception as exc:
        raise exc
    # Always restore sys.stdout/err if necessary
    finally:
        sys.stdout, sys.stderr = orig_out_err

def some_fun(i):
    print("Fee, fi, fo,".split()[i])

# Redirect stdout to tqdm.write() (don't forget the `as save_stdout`)
with std_out_err_redirect_tqdm() as orig_stdout:
    # tqdm needs the original stdout
    # and dynamic_ncols=True to autodetect console width
    for i in tqdm(range(3), file=orig_stdout, dynamic_ncols=True):
        sleep(.5)
        some_fun(i)

# After the `with`, printing is restored
print("Done!")

 

スレッド、間隔、およびミニターの監視

tqdmは、効率を高め、オーバーヘッドを減らすためにいくつかのトリックを実装しています。

  • 不要な頻繁なバーリフレッシュを避ける: minintervalは、リフレッシュごとに待機する時間を定義します。 tqdm常にバックグラウンドで更新されますが、最小間隔ごとに表示されます。
  • コールの回数を減らして、システムクロック/時間を確認します。
  • minitersminitersよりも構成が直感的miniters 巧妙な調整システムdynamic_minitersminitersを時間のminitersに収まる反復量に自動的に調整します。 本質的に、 tqdmは実際に時間をチェックせずにプリントするかどうかをチェックします。 この動作は、手動でminitersを設定することによっても回避できます。

しかし、高速反復と低速反復を組み合わせたケースを考えてみましょう。 数回の高速反復の後、 dynamic_minitersminitersを大きな数に設定します。 その後反復速度が遅くなると、 minitersは大きく留まり、したがってディスプレイの更新頻度が低下します。 これに対処するには:

  • maxintervalは、表示リフレッシュ間の最大時間を定義します。 同時監視スレッドは、期限切れの更新をチェックし、必要に応じて強制的に更新を行います。

監視スレッドには顕著なオーバーヘッドがあってはならず、デフォルトでは少なくとも10秒ごとに更新が保証されます。 この値は、任意のtqdmインスタンスのmonitor_intervalt = tqdm.tqdm(...); t.monitor_interval = 2 )を設定することによって直接変更できます。 tqdmバーのインスタンス化前に、 tqdm.tqdm.monitor_interval = 0に設定することにより、モニター・スレッドをアプリケーション全体で使用不可にすることができます。







-tqdm
-, , , , , , , , , , , , , , ,

執筆者: