pythonでライブラリを使用せずにちょっとしたspinnerとprogress barを作る(CLI)

たまに欲しくなるのでメモ。やっていることはエスケープシークエンスでN行戻った行頭に移動して現在のカーソルから端末の終端までクリアを繰り返しているだけ。

progress bar

ちょっとしたプログレスバーの表示。ふつうにやる分にはtqdmを使ったほうがお手軽そう。

import time


n = 3

for i in range(11):
    if i > 0:
        print(f"\033[{n}F\033[J", end="")
    for j in range(n):
        print(f"{i * 10: 2}% |{'████' * i}")
    time.sleep(0.5)
print("ok")

実行してみた結果。

asciicast

spinner

進捗が読めないものの場合はsppinnerが欲しい。きれいにやりたいならyaspinとかhaloとかある。

import itertools
import time

frames = itertools.cycle(["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "])

for i, frame in zip(range(10), frames):
    print(f"\033[1F\033[J{frame}")
    time.sleep(0.3)

実行してみた結果(ちょっと数を増やしてみた後のものだけれど)。

asciicast

terminalの出力を良い感じに伝える方法

ターミナルの出力を映像として共有したい。色々調べたけれどasciinemaを使うのが一番楽そうだった。

asciinema.org

使いかたは以下の様な感じ。

$ yay -S community/asciinema
$ asciinema rec
# なんか操作を実行して C-d
$ asciinema upload <file>

内部的には簡単なテキストファイルで保存されるだけなので編集も可能。以下のような形式で保存される(asciicastという形式らしい(?))。

{"version": 2, "width": 136, "height": 32, "timestamp": 1554249030, "env": {"SHELL": "/bin/sh", "TERM": "screen.xterm-256color"}}
[0.015064, "o", "sh-5.0$ "]
[1.85265, "o", "p"]
[2.001217, "o", "y"]
[2.101138, "o", "t"]
[2.201061, "o", "h"]
[2.368232, "o", "o"]
[2.551328, "o", "n"]
[2.668321, "o", " "]
[2.818133, "o", "0"]
[3.065166, "o", "7"]
[3.265205, "o", "spinner.py "]
[3.94974, "o", "\r\n"]
[4.007517, "o", "\u001b[1F\u001b[J◰  🌑   🕛   🚶   💛 \r\n"]
[4.508705, "o", "\u001b[1F\u001b[J◳  🌒   🕐   🏃   💙 \r\n"]
[5.00968, "o", "\u001b[1F\u001b[J◲  🌓   🕑   🚶   💜 \r\n"]
[5.510386, "o", "\u001b[1F\u001b[J◱  🌔   🕒   🏃   💚 \r\n"]
[6.011698, "o", "\u001b[1F\u001b[J◰  🌕   🕓   🚶   ❤️ \r\n"]
[6.511965, "o", "\u001b[1F\u001b[J◳  🌖   🕔   🏃   💛 \r\n"]
[7.012854, "o", "\u001b[1F\u001b[J◲  🌗   🕕   🚶   💙 \r\n"]
[7.513724, "o", "\u001b[1F\u001b[J◱  🌘   🕖   🏃   💜 \r\n"]
[8.01471, "o", "\u001b[1F\u001b[J◰  🌑   🕗   🚶   💚 \r\n"]
[8.479956, "o", "^\b"]
[8.515269, "o", "\u001b[1F\u001b[J◳  🌒   🕘   🏃   ❤️ \r\n"]
[9.02634, "o", "sh-5.0$ "]
[9.163483, "o", "\r\n"]
[9.163748, "o", "sh-5.0$ "]
[10.478949, "o", "\u0007"]
[11.759994, "o", "exit\r\n"]

animation gif

asciinema/asciicast2gifがある。内部的にはphantom.jsを立ち上げてキャプチャを取っているみたい。

docker imageが用意されている。

$ docker run --rm -v $PWD:/data asciinema/asciicast2gif [options and arguments...]

ただし絵文字系のフォントがもしかしたら不足しているのかsymbola font的な見た目になった(そして表示が小さい)。

animation gif