概要
Webサービスなんかで、大量のユーザに対してアイテムの補填をしたりすることがありあます。そのような処理に時間のかかるスクリプトが走っている間、もし何もコンソールに出力されていなかったらうまく処理が行われているのか不安になります。
エンジニアが書いたスクリプトをディレクターが使用する場合など、実装者と使用者が異なる場合、使用者はさらに不安になりそうです。
スクリプトを走らせている人が、ちゃんとに処理が行われているのか、どこまで処理が進んでいるのかを常に確認できるようにするべきです。
楽しくないコンソール出力講座
10000人のユーザに何かをするスクリプトがあるとします。特に処理の部分は書かないので、実際はユーザのデータを取得してアイテムなどを配布しているのだと想像してください。
# coding=utf-8
user_num = 10000
print "処理を開始します"
for x in range(1, user_num+1):
print u"{}/{}人目の処理を行っています".format(x, user_num)
print "{}人へのアイテム配布を終了しました".format(user_num)
はい。大変なことになります。コンソールに10000行出力されます。繰り返し1回あたりの処理に時間がかかるなら認識できるかもしれませんが、これだと今何人目なのかわかりませんね。
楽しいコンソール出力講座
そこでsysモジュール
を使用してみましょう。
# coding=utf-8
import sys
user_num = 10000
print "処理を開始します"
for x in range(1, user_num+1):
sys.stdout.write("\r{}/{}人目の処理を行っています".format(x, user_num))
print "\n{}人へのアイテム配布を終了しました".format(user_num)
これだと1行に表示されていきます。かなり見やすくなりました。まぁ今回の処理は速すぎて一瞬ですが...
timeモジュール
をimport
してfor文にtime.sleep(0.001)
とか入れたらわかると思います。
応用コンソール出力
x人中y人目という表示以外にも方法はあります。例えば2018年1月1日から31日までに登録したユーザにアイテムを配布したい、なんてこともあります。
このような場合は、「1月1日に登録したユーザの処理を行っています」という表示にすると、具体的な人数を見られなくなりますが、かなり見やすい表示になります。
ユーザが登録した日時がdatetimeモジュール
などで保存されていれば同じような感じで表示できます。
# coding=utf-8
import sys
import datetime
date = datetime.datetime.now()
sys.stdout.write("\r{}年{}月{}日の処理を行っています".format(date.year, date.month, date.day))
このようなものを繰り返しの中に組み込めばできるのですが、問題が1つあります。
sys.stdout.write()
で出力すると元の文字の上に上書きするので、1つ前よりも短い文字列を出力すると、最後の方の文字がコンソール上に残ってしまうのです。
その場合は、全日数に対して何日目を処理しているのかを出力するなど、色々考えて工夫してみましょう。
結論
何はともあれ、大事なことは使い人にとってスクリプトの処理の進捗がわかりやすく伝わることなので、そこを第一に考えてどのような出力をするのかを考えて実装すれば良いと思います。
では、素晴らしい出力ライフを!