8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

pythonでネタ進捗バーを作ってみた。

Last updated at Posted at 2021-08-15

動機のお話

簡単にいうと、進捗バーを作成したくなりました。
tqdmというパッケージを使えば簡単にできるっぽいのですが、それでは面白みがありません。
せっかくアスキーアートというものがあるのだから、暇な時間はそれを映したいなと思い、いろいろ試すことにしました。

必要な知識

まず、進捗バーを表示する際に知っておくべきことがあります。
それは、表示カーソルの動かし方です。
以下のコードを見てください。

sample1.py
import time
for i in range(10):
    time.sleep(1)
    print("\r{}".format(i),end="")

これを実行すると、表示される数字が上書きされます。
注目すべきは二つ。

1. end=""
これはprint関数のオプションにある、終端文字の指定で、デフォルトは"\n"(改行文字)です。 そのため、これを""(文字なし)に変更すると、行を下に動かさずに出力できるようになります。
2. "\r"
こちらはエスケープシーケンスというもので特殊なコマンドを意味し、入力カーソルを行の先頭に移すことができます。
つまり、end=""をprint関数に入れることで、入力後の改行をなくし、"\r"を入れることで、カーソルを前に持っていき、前の表示文字を強制的に上書きしてしまう、というやり方です。

これを応用すれば、次のようにかけます。
もし使用したいのであれば、stepの数を変更するだけで、大体なんとかなる。はず。

sample2.py
import time
progress_bar = "\r[{0}{1}] {2}%"
step = 100
for i in range(step):
    time.sleep(1)
    bar = "#" * (i//10+1)
    nobar = " " * ((step-i)//10)
    print(progress_bar.format(bar, nobar,  round((i+1) / step * 100., 2)), end="")

ここまでが基本のお話。

次に、エスケープシーケンスについて、もう少し詳しく触れます。

エスケープシーケンスで入力箇所を動かす。

エスケープシーケンスとは、ターミナルの制御を可能とする文字で、\033から始まる文字列で表します。
これを利用すれば色の変更などもできるようだが、今回はカーソルを動かすことに焦点を当てます。
使用するシーケンスは以下の通りです。これさえ使いこなせれば、いかようにもターミナル内の文字を操作できるでしょう。

\033[nA ...カーソルをn行だけ上に移動
\033[nB ...カーソルをn行だけ下に移動
\033[nC ...カーソルをn行だけ右に移動
\033[nD ...カーソルをn行だけ左に移動

ただし、Windowsではエスケープシーケンスはデフォルトでは使用できないので、設定を変える必要があります。下に参考になりそうなリンクを掲載しておきました。
また、Jupyterなどの環境はターミナルとは異なるので、上にあげたようなエスケープシーケンスは使用できないようです。

ということで、これらを用いて、動くAAを作ってみましょう。

完成品はこちら

ダンスを披露するAAを進捗バーの下に表示

コードは以下の通り

dancing_progress_bar.py
import time

progress_bar = "\r[{0}{1}] {2}%"
size = 1000
#顔文字がずれているのは自分で修正してください。
dance1 = """\
   ♪ ∧,_∧  ♪              
   ( ´・ω・) ))	               
 (( ( つ ヽ、   ♪	            
   〉 とノ )))	             
  (__ノ^(_)	            
"""
dance2 = """\
    ∧_,∧ ♪	           
  (( (・ω・` )                  
♪   / ⊂  ) )) ♪	           	
   (((ヽつ〈                 
   (_)^ヽ__)            
"""

dance3 = """\
     ∧,_∧ ♪            
  (( (    )             
♪    /    ) )) ♪	     
  (( (  (  〈	           
    (_)^ヽ__)           
"""

dance4 = """\
♪    ∧,_∧	                  
   (    ) ))	              
 (( (    ヽ、   ♪           
   〉   ノ ) ))         
  (__ノ^(_)				
"""

dance5 = """\
    ∧_∧ ♪           
   (´・ω・`)  ♪        	
   ( つ つ	           
 (( (⌒ __) ))          
    し'"""

dance6 = """\
  ♪ ∧_∧					
    ∩´・ω・`)				
    ヽ  ⊂ノ			
   (( (  ⌒)  ))		
      c し'			
"""

dance7 = """\
♪                      
     ∧_∧ ♪           
. ((o(・ω・` )(o))     
   /    /         
   し―-J            
"""

dance8 = """\
♪                     
    ∧_∧              
 ((o(´・ω・)o))       
    ヽ   ヽ ♪     	  
     し―-J	    	    
"""
dance_list = [dance1,dance2,dance3,dance4,dance5,dance6,dance7,dance8]

for i in range(size):
	time.sleep(0.05)
	progress = int ((i+1)/100)
	maxprog = int(size/100)
	bar = "=" * progress
	nobar = " " * (maxprog - progress)
	dancenum = (i//25)%8
	if i%25==0:
		print(progress_bar.format(bar, nobar,  round((i+1) / size * 100., 2)))
		print(dance_list[dancenum])
		print("\r\33[7A", end = "")
	else:
		print(progress_bar.format(bar, nobar,  round((i+1) / size * 100., 2)), end="")
	if i == size-1:
		for j in range(6):
			print(" "*40)
		print("\r\33[5A",end="")

見て察したとは思いますが、上の8個のAAをひたすら繰り返す進捗バーです。
証拠隠滅のため、進捗100%になった時にAAは消えるように調整しています。
証拠隠滅なんてする必要がない!と思った方は、下の4行を削除すればそのままになるはずです。

せっかくなので、もう一つ用意しておきました。

待機中にお茶を勧めてくるAA

progress_bar_ocha.py
ocha = []

ocha.append("""\

                       _______
       ∧__∧     /__ o、 |、
      (´・ω・)      | ・ \ノ
     旦  o)        | ・  |
     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
""")
ocha.append("""\

      ジャー       ______
        ∧__∧     /__ o、 |、
      (´・ω・) ノ  .ii | ・ \ノ
     ( o        旦 | ・ |
     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
""")
ocha.append("""\
     あ、きみもお茶のむ?
              ______
        ∧__∧    /__ o、 |、
     (´・ω・ )    | ・ \ノ
     ( o旦o      | ・ |
     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
""")

for i in range(3):
	bar = "#" * (i+1)
	nobar = " " * (2-i)
	print("\r[{0}{1}] {2}/3".format(bar, nobar, i+1))
	print(ocha[i])
	time.sleep(5)
	if i != 2:
    		print("\r\33[8A",end="")
	if i == 2:
		time.sleep(2)
		print("\r\33[7A",end="")
		for i in range(6):
    			print(" "*40)
		print("\r\33[6A",end="")

まとめ

今回、AA進捗バーを作ってみて、エスケープシーケンスの良い勉強になりました。これを応用すれば文字の色なども変えられることも分かったし、以外と学びは多かったです。
これはPython以外でも活用できるようなので、今後仕事でCなどを使う際にも活用していきたいです。

参考サイト

Qiita:Pythonで進捗表示したい!
2chのかわいいAA/顔文字まとめ
Windowsでエスケープシーケンスを有効化する方法

8
9
2

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
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?