Pythonの辞書のリストをエクセルで読み込みたいときにはjson.dump()でindent='\t'を指定すると比較的きれいに読み込める

Pythonの辞書型の要素を持つリストを、エクセルで作っている資料で使いたい時がありました。普段はVS codeでJupyter Notebookを使っているのですが、その画面イメージのままエクセルで読み込むのはどうしたらいいか、スクリーンショットではなく、データとして上手く読み込ませたいと思い、やり方を調べたところ、`json.dump()`で`indent='\t'`を指定すると比較的きれいに読み込めるということが分かりました。以下、詳細です。

### バージョン情報
以下のバージョンで確認しています。

+ Python 3.12.4
+ json 2.0.9
+ Visual Studio code バージョン: 1.96.4 

### pprint関数での表示

例えば次のような辞書型のリストがあったとします。

```py
sample = [{'store':'A','items':[{'name':'tomato','price':100},{'name':'apple','price':120}]},
 {'store':'B','items':[{'name':'cabbage','price':90},{'name':'lettuce','price':150}]}]

```

通常のprint関数ではリストや辞書の要素が改行されることなく1行で出力されてしまいます(下の画像はVS codeでjupyter notebookを使って実行した様子)。

![printの場合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/c8a0f31a-8f5a-0ce2-d62b-863debbf5936.png)


[Pythonのpprintの使い方（リストや辞書を整形して出力）](https://note.nkmk.me/python-pprint-pretty-print/)にも書かれているように、pprintモジュールのpprint関数を使うと、見やすく整形してくれます。

```py
from pprint import pprint

pprint(sample)
```
この場合は多少、`width`の設定を変えた方がいいかもしれませんが．．．

![pprintの場合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/deed300d-8961-e0be-4fa2-b0a2917688b5.png)


### ファイルへの書き出しとエクセルでの読み込み

これをcsvファイル(テキストファイル)として書き出して、エクセルで利用したいとします。[【python】print/pprintした結果をファイルに書き出す](https://www.haya-programming.com/entry/2018/01/24/192000) によると、stream引数を指定して書き出せばよい、とのこと。

```py
from pprint import pprint

with open('sample.csv', 'w') as f:
    pprint(sample, stream=f)
```

出力されたファイルをVSCodeで開くと、先程のjupyter notebookの出力セルと同じ形式で書き出されていることが確認できます。

![VScodeで読み込んだ場合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/b4c3147e-e571-d6bb-c642-87f05e3165bd.png)

これをエクセル(今回はLibreOffice Calc)で開くと、読み込み設定のウィンドウが出ます。

![コンマで区切って読み込む.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/4c8bfad8-86b6-3460-d0a6-758c129d1e6d.png)

csvファイルなので"区切りのオプション"で"コンマ"を指定して読み込むのですが、．．．

![コンマ区切りで読み込んだ場合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/c1bc279a-342b-fb17-c24b-59d19c8db9ef.png)

これでは一つのセルに複数の情報が入っていて扱いづらいですね．．．。区切りの設定に、「スペース」とか入れてもどうもきれいに読み込めません。例えば「コンマ」と「スペース」を指定すると以下のようになりました。

![コンマとスペース区切りで読み込んだ場合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/2099dfc0-f58a-17c8-3994-d3ea64d4d17e.png)

これもキーと値が別のセルになっていたり、列がバラバラ、ちょっと使いにくいと思います。

### `json.dump()`でindentにタブを設定

そこで、何かいい方法がないか調べてみると、`json.dump()`でindentにタブを設定できる、という記事([Dumping a JSON using tab indents (not spaces)](https://stackoverflow.com/questions/44819900/dumping-a-json-using-tab-indents-not-spaces))を見つけました。早速試してみると．．．

```py
import json

with open('sample.json', 'w') as f:
    json.dump(sample, f, indent=('\t'))
```

書き出されたファイルを、タブを^で表現できるエディタを使って読むと確かに区切りがタブになってます。

![json_dumpタブ区切り.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/2d363a56-1858-96ca-4691-123dac502feb.png)

で、これをエクセル(今回はLibreOffice Calc)で、タブで区切る様にしてして読み込むと、キーと値が同じセルにあり、さっきよりは利用しやすくなったと思います！

![タブ区切りで読み込んだ場合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335076/b75e9fda-ca67-5462-26b2-a0fb418ef68f.png)

ちなみに、pprint関数でも`indent`が指定できるので同じようにできるかと思って、` indent=('\t')`とやったら怒られましたorz。

```py
with open('sample.txt', 'w') as f:
    pprint(sample, indent='\t', stream=f) 

# ValueError: invalid literal for int() with base 10: '\t'
```

### 参考サイト

+ [Pythonのpprintの使い方（リストや辞書を整形して出力）](https://note.nkmk.me/python-pprint-pretty-print/)
+ [【python】print/pprintした結果をファイルに書き出す](https://www.haya-programming.com/entry/2018/01/24/192000)
+ [Dumping a JSON using tab indents (not spaces)](https://stackoverflow.com/questions/44819900/dumping-a-json-using-tab-indents-not-spaces)