Python プログラマのスキル標準化のための項目

Pythonプログラムを業務として開発する場合、チームとしてのスキルを高めることが大事。

### 前提
github を使用していること
Linuxを使用していること

## 業務で活用するパッケージの作り方
-  [スタイルのガイドライン](https://pep8-ja.readthedocs.io/ja/latest/)にそったコーディングをする。
- pythonスクリプトの書式を[black](https://pypi.org/project/black/) ([blackの解説記事](https://book.st-hakky.com/hakky/application-python-black/)) などで書式をそろえる。
- [type hint](https://docs.python.org/ja/3/library/typing.html)を書く
  - `def some_func(image):` は何を引数にとるの
  - 例：`def some_func(image: np.ndarray):`
  - 例：`def some_func(image: PIL.Image):`
  - 例:`def some_func(image: str):`
  - 他にも、imageが画像とtimestampを含めた複合的なデータ構造になっている場合もあります。
  - どのようなものかを、コードを読む人は、type hintがないと知ることが難しい。
- doc comment 
関数名・メソッド名、引数の変数名をわかりやすくすることで、
doc comment なしでも意味がとれるのを目指します。
意味がとれる場合にはdoc commentを書きません。
doc comment と実装の乖離が生じることは、害をなします。
だから、意味がとれる場合にはdoc commentを書きません。
[numpy style doc comment](https://numpydoc.readthedocs.io/en/latest/format.html)を書く

- 開発段階での予防的プログラミング
例：画像のチャネル数の確認
np.ndarray型の画像のチャネル数の確認
```python:
assert image.shape[:3] == 3
```
ライブラリによっては取得した画像が4 チャネルの場合がある。
それを機械学習の推論に与えると、誤動作する。
```python:
assert image.dtype == np.uint8
assert image.dtype == np.float32
```

- 想定する内容をわかりやすくすること
    - 色の順序が間違っていると失敗してしまうライブラリには、わかりやすい変数名を！
    - image よりも rgb_image などとする。

- サポートするpythonのバージョンの範囲を明確にする。
特にnumpy のバージョンには留意すること。
2024年の時点では`numpy<2.0` としておくのがよい。



- 自作コードを、モジュールとサンプルスクリプトに分離する。
- モジュールのパッケージ名を決める。
- モジュールのファイルはモジュールのディレクトリに移動する。
- 自作モジュールのインストール手順をsetup.cfg に書く [setup 設定ファイル (setup configuration file) を書く](https://docs.python.org/ja/3.11/distutils/configfile.html)
     とりあえず、まずはsetup.cfgでの書き方を示します。（）
     最近はpyproject.tomlを代わりに使うのが推奨されています。
     
- モジュールのバージョン情報を追加する。
- モジュールをlocal にインストールする。
 
```
# 従来のやり方
python3 setup.py install
# 最近のやり方
python3 -m pip install .
```
  (pipを使うinstall 手順は、setup.cfg、pyproject.toml の両方で共通です。)
- pytestを使ってテストできるようにする。
  - test データを用意する。
  - ある動作をしたときの期待値と実際の値とを比較する


- pytest の作り方
- リポジトリにtestのディレクトリを追加します。
- 目標
以下のようにしてテストができるようにします。
```
cd test; pytest test*.py 
```
- テストをモジュールの説明になるように開発する
よりよいテストは、モジュールの動作の説明としてわかりやすいように実装する。
何かの理由により実装が壊れたときには、見つけられように書く。

- 動作テストと性能の評価は別物にする
    - pytestでの動作テストは、典型例での動作の検証にして、実施例の数を減らす。
    - 機械学習などの推論の性能に関する指標の評価はpytestには含めないようにする。

詳しくは [pytest の使い方](https://qiita.com/nonbiri15/items/c3c6567eec4b1acfa8a5)
  
 whlの作り方
 ```
 python setup.py bdist_wheel
 ```
ちなみにpyproject.toml では [pyproject.toml をベースにwhl ファイルを作る手順](https://qiita.com/nonbiri15/items/5b517cf1b52e5ed6e1f9)
 
そうすると*.whl ファイルが作成されます。

## python 以外のライブラリの環境構築
```
apt install パッケージ名
```

- 必須モジュールとそれ以外とを区別する
組み込み分野の場合、描画用のライブラリは不要になることが多い。
matplotlib 
opencv は本当に必要か
cv2.imread()ではなくimageio.imread()で十分なことはないか。

## 環境を壊さないためにDockerを導入する
Dockerfile を書く
docker環境で、host環境のディスクをマウントする。
docker環境で、X11の出力をhost環境で表示する。

 
## データファイルが大きいとき
- 例： Google Drive にデータを置く場合
  gdown を用いてデータをダウンロードする。

 
## Makefileを作る
ローカルPC上で必要な作業が簡潔するようにMakefileを書く
- build (C++やCythonなどのコードからbuildする必要がある場合)
- install (pythonモジュールのインスール)
- test (pythonの実行)
- whl (whlファイルの作成)
- reformat (blackなどでスクリプトの書式の整形)

## 継続的インテグレーションのための作業
例 Giuhub にコミットしたたびに、CircleCIで自動化テストを実行させる。
    例 CircleCI のためのconfig.yml を書く。

例: github actions
[JetsonでGitHub ActionsのSelf-hosted Runnerをサービスとして動かす](https://qiita.com/ynott/items/8ec1dbfe14f3225bbe70)


組み込み分野での開発では、AMD64ではないアーキテクチャでのソースコードの開発をすることがある。
NVIDIA Jetson AGX Orinでの自動化テストは、AMD64のアーキテクチャのサーバー上では動作できない。
そのため、コードを開発しているJetson上でテストを自動化するのがよい。


## packagecloudへの登録
- 業務の範囲で共有するパッケージを社内で共有するには, packageCloudを利用します。
- PackageCloud はパッケージへのアクセスコントロールをしてくれます。
- バージョンごとのwhlファイル、あるいはdebファイルを管理できます。
### packageCloudからのダウンロード
- PACKAGECLOUD_TOKEN を利用
- 例：packageCloudからのダウンロードし、ローカルでpip を使ってインストールする。

# 学習用・評価用の大量のデータの扱い（入門レベル）
段階０：ユーザーがバックアップを考えなくていいレベル
  Google　Drive にフォルダを置く
  gdown でそのフォルダをコピーする

データは追加するだけのデータか？　データファイルのバージョン管理が必要になるか？

### データを追加するだけの場合の手順
[データ レイクは、大量のデータを元の形式で取り込んで保存する集中型リポジトリです。その後、データを処理して、さまざまな分析ニーズの基礎として使用できます。](https://azure.microsoft.com/ja-jp/resources/cloud-computing-dictionary/what-is-a-data-lake)


[Git LFS からDVC(Data Version Control) に移行した話](https://qiita.com/nonbiri15/items/54c1fac76a8af5e51fdf)
　この記事では、機械学習用にアノテーションなどの処理が済んだデータをバージョン管理する話を書いています。
　データ全体の管理の責任者が一人いて、その一人が作業をする前提で書いています。
　学習用のデータをサブフォルダ単位で追加していくことを想定しています。
　アノテーションの付け直しなどを想定していないので手順を単純化しています。

[機械学習用の画像のデータレイクを作る](https://qiita.com/nonbiri15/items/70ab04440211e35ebff2)
 この記事では、上記の作業の前段で、個々の撮影などでデータを取得した時点でのデータの管理を想定しています。
```
--uniq                
  撮影した時点でユニークな名前になっていない場合に、ユニークな名前に変更する。
--show_local        
  ローカルデータのディレクトリを示す。
--show                
  リモートストレージにおいてあるディレクトリを示す。
--push ローカルデータのディレクトリ          
  ローカルデータのディレクトリ　をリモートストレージにコピーする。
--safe_remove ローカルデータのディレクトリ
  リモートストレージに該当のデータがあることを確認して、ローカルデータのディレクトリを削除する。
--get 該当のシーンのフォルダ
  リモートストレージの該当のシーンのフォルダをローカルにコピーする。
```

これらの管理をすることを想定した記事になっています。
データの取得をして、生データを登録する作業を行う人が複数人いるときに、バッティングを生じないようにすることを
目的とした記事です。
 
## 評価の自動化
- 評価の自動化をできるスクリプトを用意します。
- ドキュメントを自動生成させます。
- jupyter notebook を使うという方法もあります。

#### 何もしていないのに勝手に壊れた対策
依存ライブラリのバージョンがあがったときに、「何もしていないのに勝手に壊れた」が発生します。
その対策を、あなたの業務を引き継いだ人がしなければならなくなります。
そのためには、github で管理しているtestコードを十分にメンテナンスしておきます。
testを実行したときに、後方互換性がなくなった依存ライブラリを見つけられればラッキーです。
ここで管理しているパッケージが業務用重要ならば、引き継ぎをしっかりしておくことです。

## 最後に
これらの項目は、学習によって簡単に習得できるものです。
あなたの部署で必要な項目を取捨選択してください。

## 付記
- requirements.txt:
    python3 -m pip install -r requirements.txt 
- Makefile:
	Linux の環境でのツール
	Cmakeと組み合せて使うこともある。
- CircleCI config.yml:
	yml形式で、Makefile相当のことをCircleCIのサーバー上で実行するしかたを記述しています。

- Docker Dockerfile:
	Docker環境を構築する手順を記述しています。

- Python setup.cfg あるいは、pyproject.toml
	Python環境を構築するためのツール
	python のライブラリをインストールします。必要に応じては、ソースからのビルドも行います。
	
これらのツールが似た内容を含んでいるので、なるべく設定が楽なようにそろえていくのがいいと思われます。
pyproject.toml　にすれば、Make, CicleCI, Docker に共通に反映できるでしょうか

## 自作参考記事
- [Pythonでのカメラインタフェース](https://qiita.com/nonbiri15/items/8fa8c4ab5e60b71ccace)
- [pythonでのデータファイルの扱い方](https://qiita.com/nonbiri15/items/247b8367ae5f10e9a134)
- [サービスの集まりとして全体システムを作る](https://qiita.com/nonbiri15/items/f6f34873f9e905110630)
- [pythonプログラムをモジュールベースで開発する](https://qiita.com/nonbiri15/private/7825ff401bd4bd480537)
- [pythonモジュールの完成度を高める](https://qiita.com/nonbiri15/items/a63234ca36d3ddb4f27e)
- [機械学習全般のできる画像認識屋になる方法](https://qiita.com/nonbiri15/items/c0b935f92ff72603ae06)

## 参考記事 
- [Pythonパッケージの作り方](https://qiita.com/studio_haneya/items/9aad8f9ede11e58b41a8)
  setup.cfg を使う場合の説明です。
- [【packagecloud】pythonのパッケージをpackagecloudで管理する](https://qiita.com/Yarimizu14/items/12ea87fa577e6734962d)