pythonでのデータファイルの扱い方

## はじめに
主に画像認識屋に向けて
pythonでのデータファイルの扱い方を
標準的なデータ形式について知ってしまうためのものです。

## json
Python のdict型と対応の付けやすい、キーと値の組合せで読み書きできるデータフォーマットです。
[json --- JSON エンコーダーとデコーダー](https://docs.python.org/ja/3/library/json.html)
json フォーマットはCVATでのアノテーション結果の標準的なデータ形式に使われています。
アノテーション結果をの場合には、アノテーションファイルに対応したライブラリを使うのがおすすめです。

## yaml
[PyYAML](https://pyyaml.org/wiki/PyYAML)
CircleCIのconfig.yaml はyaml形式です。

## toml
pypi [toml](https://pypi.org/project/toml/)
github [toml](https://github.com/uiri/toml)
python のパッケージ管理用のファイルpyproject.toml はtoml形式です。
python 3.11 以降だとlibtomlが標準ライブラリに追加されています。
[tomllib --- TOML ファイルの解析](https://docs.python.org/ja/3.12/library/tomllib.html)


## npy
numpy がデータを保存するデータ形式です。
numpyではIEEEのデータフォーマットで数値データを保存できます。
NaN, PosInf, NegInfなどの値を持つことができます。

[numpy.save](https://numpy.org/doc/stable/reference/generated/numpy.save.html)
[numpy.load](https://numpy.org/doc/stable/reference/generated/numpy.load.html)
## pickle
pythonオブジェクトをserialize, deserializeできるモジュールです。
学習済みのclassierのインスタンスをserialize, deserializeすることもできます。
そのため、とても危険です。
また、pythonや使用したモジュールのバージョンの影響を受ける点も厄介です。
scikit-learn それ自体には、学習結果を保存する手段が用意されていません。
そのため学習後のclassifierのインスタンスをpickleしてしまうことがありました。
でも今は、onnxファイルで保存することができます。
scikit-learnで学習した結果をonnxに変換する方法が以下の記事に書かれています。
[scikit-learnの学習結果をpickleしない](https://qiita.com/nonbiri15/items/d78613a1ab7bd515d867)

## MATLAB mファイル
MATLABでデータを保存する形式です。
scipyのライブラリで開くことができます。
[scipy.io.loadmat](https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.loadmat.html)
[matlabで配列を書き出してPythonで読み込む](https://qiita.com/oozzZZZZ/items/414c893deea66bd7ed3d)

# CSV ファイル
[numpy.loadtxt()](https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html#numpy.loadtxt)
delimiter="," とする。

[numpy.save()](https://numpy.org/doc/stable/reference/generated/numpy.save.html)
## pandas でcsvファイル
[pandas.read_csv](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)
[pandas.DataFrame.to_csv](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html)

## EXR
高ダイナミックレンジの画像のフォーマット
[OpenEXR画像ファイルをpythonで読みこむ](https://qiita.com/studio_haneya/items/3adeae5fe527023eed11)

## ply 
点群データ
表示には
[meshmal](https://www.meshlab.net/)
[Open3D](https://www.open3d.org/docs/latest/tutorial/geometry/file_io.html)

### 付記
データ形式の標準化が進んでいるので、以前よりも扱いが楽になってきている。
- CPUのエンディアンによって影響を受けやすいフォーマットは使われなくなってきている。
- そのため、X86でもARMでも同じバイナリデータで扱える。

------
## データの永続化の手段
#### sql のデータベースを読み書きする。
- [sqlite3 --- SQLite データベース用の DB-API 2.0 インターフェース](https://docs.python.org/ja/3/library/sqlite3.html)
#### [REDIS](https://redis.io/)
REDISでは、SQLのような構造化されたデータではないデータを扱うことができます。
- pypi [redis](https://pypi.org/project/redis/)
- [開発者のためのRedisチュートリアル(1)](https://meetup-jp.nhncloud.com/3125)
 複数のサービス間で同一のredisサーバーにアクセスすることで、変数の受け渡しをすることができます。

#### dataclass 
Python のdataclassはjson形式でserialize できます。
pypi [dataclasses-json](https://pypi.org/project/dataclasses-json/)

```.py:
from dataclasses import dataclass
from dataclasses_json import dataclass_json


@dataclass_json
@dataclass
class Person:
    name: str


person = Person(name='lidatong')
person.to_json()  # '{"name": "lidatong"}' <- this is a string
person.to_dict()  # {'name': 'lidatong'} <- this is a dict
Person.from_json('{"name": "lidatong"}')  # Person(1)
Person.from_dict({'name': 'lidatong'})  # Person(1)

# You can also apply _schema validation_ using an alternative API
# This can be useful for "typed" Python code

Person.from_json('{"name": 42}')  # This is ok. 42 is not a `str`, but
                                  # dataclass creation does not validate types
Person.schema().loads('{"name": 42}')  # Error! Raises `ValidationError
```
上記のpypi にある例題を転載。

データのserialize, desierializeはネットワークインタフェースで、データを転送する際に利用することがあります。
テキストファイルにしてしまえば、OSの違いやCPUのエンディアンの違いを受けません。


#### Protocol Buffers
Protocol Buffers（プロトコルバッファー）は構造データのシリアライズを目的とした技術スタックである。
github [protobuf](https://github.com/protocolbuffers/protobuf)
pypi [protobuf](https://pypi.org/project/protobuf/)

Protobufの良い点は、複数のコンピュータ言語をサポートしていることです。
送信元と受信先で使用言語を変えることができます。

解説記事の例 [pythonの型定義を使ってprotobufを出力してみる。](https://pod.hatenablog.com/entry/2020/05/11/003108)