とある京大生の作業ログと日々の雑記

コンピュータサイエンスについて学んだことを可視化したり日々の雑記をまとめてます。

ターミナルへの出力に色つけたりうまいこと改行する話

こんばんは!コミさん(@komi3__ )です!




近況報告として、もうすぐで春休みが終わるということでなかなか絶望しています!





また授業を受けなければならないのか....ってなってます。


じっと座って静かに人の話聞いてるのめちゃくちゃ嫌いなんですよねw





まあもう卒業単位分の単位まであと少しなので我慢するとします。





今日の話題は、先日公開したPyGameでSokobanの環境をいじってて




「あれ、これもう少し高速化できるんじゃね?」



ってこととか



GUIでのレンダリングCUI同期した方がデバッグとか色々捗るんじゃね?」




ってことなどを思って、現在全面的に改修中です。




そんな中で、ちょっと良さげなテクニックなどをここでパパッとまとめておこうかなって感じで、今日はメモ書き程度の記事になります。



外部テキストファイルへのアクセス

まずSokoban改修ポイントその1として、マップデータを外部のデータファイルとして保存しておいた方がその後に繋がりそうじゃね?ってことで、まずはそこらへんをいじります。


with構文

普通にPython数値計算やってる限りだとあんまりwith構文って使わないと思う。(少なくとも自分はあんまり使わない)




あ、でもTensorFlowの実装とかだとよくwith構文見かけるかも?




例えばこんな感じでstageのデータファイルが何個かあるとします。


f:id:komi1230:20180322214137p:plain


このrender_cui.pyというのはデバッグ用に用意したものなので気にしないように。



ファイルにアクセスするときのwith構文はこんな感じ。


with open("stage1.dat", "r") as f:
    print(f.read())

このときの出力はこんな感じ

f:id:komi1230:20180322214642p:plain


(てかファイルの中身はこんな感じになってました)


f.read()だと1文字ずつ取り出すんかな?



あんまり知らない。分からなければググる所存である。



1行ごとに取り出すときは

with open("stage1.dat", "r") as f:
    print(f.readline())

って感じ。



openのファイルパスの横の"r"は読み取りのとき。



書き込みのとき"w"にするとf.write()とかで書き込みができる。



そして調べてみたら"rw"で読み書きの両方に対応したやつがあるらしい。



とりあえず"rw"ってしとけばなんか良さそう(?)




with構文は、普通にopenでファイルにアクセスしたときにclose()でちゃんと閉じないとファイルの書き込みが正しくされなかったりするらしく、その点with構文はclose()しなくても勝手に閉じてくれるから嬉しい。



ファイルにアクセスするときはwith構文を使うのが無難。


numpyでファイルにアクセス


数値計算のツールとしてpythonのモジュールとしてとても強力なやつ。



乱数生成から和の計算、高速フーリエ変換微分積分までなんでもこなしてくれる。いい気分。




ぜひともお友達になっておきたい。




そんなnumpyくん、データロードにも対応している。




流石に多才過ぎてセブンイレブンもびっくりだよね。いい気分。



Map = np.loadtxt("stages/stage"+stage+".dat", dtype=int)

こうするとnumpy配列として今回のマップデータをゲットしてくれる。




APIに関してはnumpyの公式ドキュメントを見てみよう。ぼくは知らない。




numpyくんはCベースで書かれてるモジュールだからとても早い。




こんな感じで外部ファイルへのアクセスは色々やり方ができるので状況に合わせて選ぼう。


ターミナルへの出力に色をつける


ターミナルってbashでプロンプトいじくってなかったら基本的にはみんな白黒。



ぼくはそこらへんいじりまくってるのでちょっとオシャレなんだけど↓

f:id:komi1230:20180322220241p:plain



プロンプトのいじり方とかは以下のQiitaのページを参考にしよう。

qiita.com



とてもよくまとまっているので一読あれ。



さて、ターミナルの出力として白黒だとちょっとテンションが下がる。てか見にくい。

f:id:komi1230:20180322220836p:plain


これがこんな感じだとちょっと嬉しい。

f:id:komi1230:20180322220901p:plain



ということで色付けの方法は以下の通り。

class Colors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

if __name__ == "__main__":
    print(Colors.HEADER+"fuckin' Kyoto Univ"+Colors.ENDC)

こんな具合で使える。


色の一覧としては以下の通り。

f:id:komi1230:20180322221304p:plain


ENDCというのがノーマルの色らしい。

色付けを使って迷路を綺麗に

以上のやつを合わせ技でやると綺麗な迷路が描ける。

def map_show(Map_):
    counter = 0
    for j in Map_:
        for i in j:
            if i == 0: # field
                print(Colors.ENDC+" "+Colors.ENDC+",",end="")
            elif i == 1: # wall
                print(Colors.HEADER+"#"+Colors.ENDC+",",end="")
            elif i == 2: # barrel
                print(Colors.OKBLUE+"B"+Colors.ENDC+",",end="")
            elif i == 3: # target
                print(Colors.OKGREEN+"T"+Colors.ENDC+",",end="")
            elif i == 4: # target
                print(Colors.WARNING+"A"+Colors.ENDC+",",end="")
            else:
                pass
        print("")


print("text", end="")のところで、カッコの後ろの方でend=""ってやると改行しないで連続で出力してくれるらしい。



printはPythonの中でも一番よく使ってる関数なのに知らなかった。



んー灯台もとくらし。


まとめ

そんな難しい技じゃないけど、出力をきれいにする技がたくさんあることが判明。



ターミナルへの出力がきれいだとなんか頭良さそうに見えるよね(?)




もっとPythonの気持ちになろうと誓った春の夜であった。



〜完〜