漆黒な技術メモ

管理人が必要に応じて自分のメモを好き勝手に投下するたまり場的ブログ

【ちょっと技術的なことAdventCalender】改行区切りのログ出力をExcelとかで使えるようにCSVに変形するPythonスクリプト

この記事はちょっと技術的なことAdventCalenderの15日目です。
気づいたらもう折り返しを過ぎていますね…

プログラムを実行したときのログ出力

って、大体こんな感じで出力するようにプログラム組んでいる方が大半だと思います。

time : 10:00
power : on
value : 1

time : 10:10
power : off
value : 0

time : 10:20
power : on
value : 2

...

まあ実装上この形式で書くのが一番楽ですし、ログとして書く分には何も問題ないのですが… ある時、このログをExcelなどで集計しなくてはならない…!!なんてことになったら、この形式でやるのは超面倒ですね…

time,power,value
10:00,on,1
10:10,off,0
10:20,on,2

とかにできるのが一番理想です。
と、そんなことを実際にしなくてはならない場面に遭遇してしまったので、スクリプトを書きました

実際に作ったpythonスクリプト

引数でファイル名を指定します。空白行をCSVの行の分け目と認識するようにしています。
また、カラムはブロックごとに異なっても(途中から"Battery"カラムが増えたり、消えたり) 大丈夫なようになっています

#coding: utf-8
import sys

if len(sys.argv) < 2:
    print "usage filename"
    sys.exit(1)
filename = sys.argv[1]

f=open(filename)
lines=f.readlines()
valueText=""
columnTitles=[]
textBuf={}
for line in lines:
    if '\n' in line[0]:
        for col in columnTitles:
            if col in textBuf:
                valueText += textBuf[col]+","
            valueText+=","
        valueText += "\n"
        textBuf.clear()
    else:
        sptline=line.replace("\n","").split(":",1)
        if sptline[0] not in columnTitles:
            columnTitles.append(sptline[0])
        textBuf[sptline[0]] = sptline[1]

for col in columnTitles:
    print col+"," ,
print ""
print valueText ,

これを使って

$ python parser.py log.log > log.csv

とかやれば、変形できます。

実行結果

こんな感じです

$ cat status.log
time:2016/12/11 23:32:32
SSID:gp30
Mode:MultiShot
SubMode:TimeLapse
Recoding:True
Num. of taken:268
Num. of remaining:11794
SDcard:True
Battery:3

time:2016/12/11 23:40:25
SSID:gp29
Mode:MultiShot
SubMode:TimeLapse
Recoding:True
Recode:test
Num. of taken:278
Num. of remaining:11794
SDcard:True
Battery:3

$ python genlogparser.py status.log
time, SSID, Mode, SubMode, Recoding, Num. of taken, Num. of remaining, SDcard, Battery, Recode,
2016/12/11 23:32:32,gp30,MultiShot,TimeLapse,True,268,11794,True,3,
2016/12/11 23:40:25,gp29,MultiShot,TimeLapse,True,278,11794,True,3,test,

今日はここまで、それでは!!