60: Raspberry Pi 3 でデータを保存する

# はじめに

こちらは
[Arduino と Raspberry Pi の違いのまとめ](https://qiita.com/KZ2/items/5e0e79f84e4dd26bd373)
の個別記事で、Raspberry Pi 3 でデータを保存する。

# 目的
Raspberry Pi3 で動作する python の GUI アプリケーションの動作ログを残したい。設定したパラメータを記録して、それが実際にどうだったか振り返り、次の動作に反映させるためである。

microSD カードから起動する Raspberry Pi3 は、同時にファイルを保存することもできる。Arduino でもできることではあるが、今後、network 経由の保存となると、Ethernet Shield を使うとか、無線対応の Arduino 使うとかになって、価格も高くなってくるので Eternet および Wi-Fi が標準でついている Raspberry Pi3 を使うことにする。

ここでは、CSV と、JSON の二つを読み書きする。

## CSV
まずは、カンマで区切ったデータ、いわゆる CSV を作る。CSV なら Excel などで読み込んで処理しやすいからである。library は import csv してから利用する。

指定したファイル名でファイルを`追記モード`で開いて、データを書き込む。ここでのデータは変数ではなくて、完全に手動で作成した文字列のデータである。

```python:070_csv.py 
import csv

with open('a1-log.csv','a') as f:
    writer = csv.writer(f)
    writer.writerow([1,'audio','100'])
    writer.writerow([2,'video','568'])
    writer.writerow([3,'movie','1250'])
f.close()
print('done. see a1-log.csv')
```

```bash:結果
1,audio,100
2,video,568
3,movie,1250
```

次。元のデータをsplit()で分割する場合。split()関数は、指定した区切り文字で処理すると、そのようなデータを返す。

```python:071_csv.py 
import csv

word = "Good morning, Hello, Good night, bye, bye-bye"
words = word.split(',')

with open('start.csv', 'w') as f:
    writer = csv.writer(f)
    writer.writerow(words)
f.close()
print("done. see start.csv.")
```

```bash:結果
Good morning, Hello, Good night, bye, bye-bye
```

さて、ここまでで複数の変数のデータを CSV で保存することができるようになった。次に、CSV の生成時にその日時をつけて、データをはき出す処理を付加する。日時がないと、いつの動作logか分からなくなるためである。先頭の rec_ とかないほうが後で Excel などで処理しやすいかもしれない。日付のフォーマットも自由に指定できるので、後々どう活用するかで決めればよいだろう。

```python:072_csv_time.py 
import csv
import datetime

now = datetime.datetime.now()
recordtime = 'rec_{0:%Y%m%d}'.format(now)
print("recordtime = %s" % recordtime)

data = "foo,bar,baz"
data = recordtime + "," + data
data = data.split(',') 
print("data= %s" % data)

with open('log.csv', 'w') as f:
    writer = csv.writer(f)
    writer.writerow(data)
f.close()
print("loggging done. see log.csv")
```

```bash:結果
rec_20180606,foo,bar,baz
```

実際のアプリケーションでは、data のところを 変数名.get() などで取得してきて、自分で CSV 形式を作って保存すればよい。例はこちら。

```python:data生成の例
data =  v1.get() + "," + v2.get() + "," + v3.get() + "," + v4.get()
```

これで CSV形式で日時を付加しつつ、データを保存できるようになった。




## JSON
JavaScript Object Notation

次に JSON で保存する。JSON とは [RFC8259](https://tools.ietf.org/html/rfc8259) などで規定されているデータフォーマットである。ここでは、network 経由のやりとりを想定して json を使えるようにする。JSON について詳しくは、wikipedia などを参照すればよい。

まずは、保存の前に JSONのファイルを読んで表示する処理の例である。

```py:054-load-json.py
import json

a = open('sample.json')
b = json.load(a)

print(b)
```

json ファイルを開いて、loadして、printしているだけである。
しかし、これだと出力が改行されていなくて見にくい。

元の json を下記に示す。

```sh:sample.json
{
 "coffee":{
  "vendor": "Morihico",
  "roast_type": "French",
  "roast_date": "2018-06-09"
 },
 "configuration":{
  "temp": 93,
  "profile": 1,
  "first_pour": 2.3,
  "steam": 30,
  "pour": 2.4,
  "wait": 8.0,
  "repeat": 5
 }
}
```

こうなって一行にだーと連続表示になってしまう。

```bash:output

$ python 054-load-json.py
{u'coffee': {u'roast_date': u'2018-06-09', u'roast_type': u'French', u'vendor': u'Morihico'}, u'configuration': {u'profile': 1, u'repeat': 5, u'temp': 93, u'first_pour': 2.3, u'pour': 2.4, u'steam': 30, u'wait': 8.0}}
```

次にファイルからではなくて、プログラム内でJSONのフォーマットを作って出力する例である。

```
py:055-dump-json.py 
import json
 
v1 = 10
v2 = 13

dic =  {
 "profile1": { 
 "coffee" : v1, 
 "temp" : "91"
 } ,                
 "profile2" : {
 "coffee" : v2, 
 "temp" : "93"
 }
}
 
a = open('sample2.json', 'w')
json.dump(dic, a , indent=4)

print("done. check sample2.json")
```

dic でデータを作り、openでファイルを新規に開き、dumpしている。出力のindent数を決めることができる。ここでは4である。
最後のprintは単にどのファイルを見たらよいかの自分用のhelpみたいなものである。

実行した出力はこうなる。

```bash:output
$ cat sample2.json 
{
    "profile1": {
        "coffee": 10, 
        "temp": "91"
    }, 
    "profile2": {
        "coffee": 13, 
        "temp": "93"
    }
}
```
きれいにindent=4で整形されている。

というわけで、同じデータを CSV と JSON形式で保存する例である。

```py:056-dump-csv-json.py
$ python 056-dump-csv-json.py 
recordtime = 2018-06-16-0842
data= ['2018-06-16-0842', 'foo', 'bar', 'baz']
loggging done. see log.csv
loggging done. see log.json
```

```console:output
$ cat log.csv 
2018-06-16-0842,foo,bar,baz

$ cat log.json
{
    "log1": {
        "date": "2018-06-16-0842", 
        "name2": "bar", 
        "name3": "baz", 
        "name1": "foo"
    }
}
```

これを実現するためのsampleはこちら。 共通部分は、日付を出すところで、その後、CSV と JSON で表示している。

```py:056
$ cat 056-dump-csv-json.py 
# modules
import csv
import json
import datetime

# date
now = datetime.datetime.now()
recordtime = '{0:%Y-%m-%d-%H%M}'.format(now)
print("recordtime = %s" % recordtime)

# CSV
data = "foo,bar,baz"
data = recordtime + "," + data
data = data.split(',')
print("data= %s" % data)

with open('log.csv', 'w') as f:
    writer = csv.writer(f)
    writer.writerow(data)
f.close()
print("loggging done. see log.csv")


# JSON
v1 = "foo"
v2 = "bar"
v3 = "baz"
dic =  {
 "log1": {
 "date": recordtime,
 "name1" : v1,
 "name2" : v2, 
 "name3" : v3
 }
}
f_json = open('log.json', 'w')
json.dump(dic, f_json, indent=4)

print("loggging done. see log.json")
```

# まとめ
これで自分の好きな形式に CSV と JSON で保存できるようになった。
次はこれらの保存データを使ってグラフ描画を行う。


# 参考web site
[1] python documentation - 13.1. csv — CSV File Reading and Writing, https://docs.python.org/2.7/library/csv.html#module-csv
[2] python documentation - 18.2. json — JSON encoder and decoder, https://docs.python.org/2.7/library/json.html?highlight=json
[3] RFC8259, https://tools.ietf.org/html/rfc8259