役に立つ(と思っている)自作Pythonモジュールがある。
それが、業務で必ず使うモジュールだったり、再利用する頻度が高いなら、モジュールの完成度を高めていこう。
書く必要があるコードを書こう
-
再利用する価値があるか。
- 他の人も使いたいと思うか。
-
既存のOSSで代替できないか。
-
独自ライブラリとするよりは、既存のOSSに追加したほうがよくないか。
既存のOSSの実装の方は有効であるならば、自分の努力は、いいものをよりよくする方向に向けたほうがいい。
独自実装は、自分の勉強と割り切る。
-
独自ライブラリとするよりは、既存のOSSに追加したほうがよくないか。
-
使う目的は明確に、単一の役割を上手にこなすだけのことを考える。
-
別の目的がでてきたら、それは別モジュールにしよう。
余計な機能をつけると、無駄な作業が発生して、手離れが悪くなる。
実行したい内容が明確であれば、手離れも楽になる。
-
別の目的がでてきたら、それは別モジュールにしよう。
README.md
-
README.md は簡潔に
1行での要約を書く。
何ができるのかのデモを書く
必要に応じて図やグラフ・画像を加える。
実行環境の条件を書く
インストール手順を書く
pythonモジュールのインストールが必要なものはpyproject.toml に書く。 -
世界に向けて発信するコードならば、ASCIIの文字コードにする。日本語を含めない。
grep -P '[\p{Hiragana}\p{Katakana}\p{Han}]' -r path_to_your_repository
最初は日本語でいいから、わかりやすく書く。
有用なソフトウェアのgithubをまねて章立てを書く。
それを英語に直すには、機械翻訳で簡単だ。
-
次の依存性が、READMEなどでわかること
- 特定のデバイスが必要である場合
例:特定のカメラ(3Dカメラ) - 商品として購入する必要のあるライブラリを利用している場合
- 特定のデバイスが必要である場合
- 何の目的のソフトウェアかわかるような画像をREADME.md の表示に追加する。
-
スクリプト、コマンドの使い方は
-h
オプションで表示されるか。 - 最低限の実行をするために必要なサンプルデータを用意しておく。
pyproject.toml
-
pyproject.toml を書いてあるか
従来のrequirement.txt や、Dockerfile中のpip install の記述は減らせる。
開発時にだけinstallすれば十分なものはproject.toml ファイル中に記述してあるか
pyproject.tom: [project.optional-dependencies]に記載しているか。 -
整形ツールをpyroject.toml に記載したか
-
1行の文字数を記載しよう。
例:
-
1行の文字数を記載しよう。
[tool.black]
line-length = 120
-
lintツールのpyroject.toml に記載したか
- lint系ツールで確認できる内容
- 無駄なimport削除したか。
- PEP8 命名規則に従った命名になっているか
- 非公開にすべきデータ、メソッドは、"_"で始めてあるか
- type hintを書いてあるか
-
主旨の違いに応じてモジュールファイルを別にする。
-
開発時にだけ必要なものは、分離しやすいフォルダ構成に。
Makefile
-
make test
でpytestが実行するようにMakefileなどを書いてあるか -
make reformat
で自作部分のpython ファイルの書式をblack などで記述をそろえられるように書いてあるか -
whl ファイルを作る手順 を追加する。
apt install -y python3.8-venv
python3 -m venv venv
. venv/bin/activate
python3 -m pip install build
python3 -m build
python モジュール
-
どのディレクトリで実行しても、必要なデータファイルにアクセスできる。
-
標準出力へのprintを減らす(なくす)
表示を見やすくしたい-
進行状況を示すにはtqdmを使うといいね
-
loggingを使う。
どうしても必要なものはloggingを使って、モジュールからのログ、もしくは、プログラムからのログとして出力させる。
logging --- Python 用のログ記録手段 -
journalctlでログを見れるようになっていることを確認する。
journalctl -u [サービス名]
で実行すると[サービス名] 分だけのlogが表示される。
これを使うと、目的のサービスが、どういう具合に推移したのかが、logに吐き出された内容を元に確認できる。他の出力と混在しないし、コンソールの彼方に消え去ることもない
-
-
出力ファイルを一般的なデータ形式にする。
例:独自テキストファイルよりはJsonファイル。
例:独自バイナリデータよりは、npyファイル。 -
例外処理
- 発生した例外の種類を区別するように必要な例外処理を書く。
- ^C(コントロール+C)以外での終了方法を用意する。
-
file のopenにwith 文を使う。
スコープの外にきた時に終了処理が実行されるようになります。
例:次のように書いても自動でclose()されます。
with open("outfile.txt", "wt") as f:
f.write("message\n")
バージョン番号
- モジュールのバージョン番号を定義する。
- importしたモジュールでバージョン番号がわかるようにする。
- whl などのパッケージのファイル名にバージョン番号が含まれていることを確認する。
LICENSE
- 利用者が困らないLICENSEを選択するのがいい。
- public のリポジトリになっているのに、LICENSEの記述がないと利用に困る。
利用者がやりがちな失敗の可能性があったら、対策をとっておこう。
例:3 channelの画像を想定しているのに、4 channel の画像が入ってきたとき
選択肢 1: assertで終了させる。
asssert image.shape[2] == 3
選択肢 2: error ログを記録する.
if image.shape[2] != 3:
logger.error('invalid image.shape[2]: expected = 3 ')
選択肢 3:Exceptionを発生させる。
if image.shape[2] != 3:
raise ValueError("image channel must be 3.")
選択肢 4: 何もしない
ほんとうにトラブルが発生する場所まで、先送りする。
データのダウンロード
選択肢1:
データをダウンロードする手順を、README.md に明確に書く。
選択肢2:
データをダウンロードする必要を生じたら、自動で取得させる。
- 学習済みのモデルのように大きすぎるものをgithub におかない。
- Google Driveでも、自分のアカウントがなくなったら、削除されてしまうような場所を避ける。
- 十分に有用なものは、huggingfaceに登録する。
別環境でのダウンロード・実行を確認する。
- 自分の環境では動作するのに、他の人の環境では動作しないということが起きるかもしれない。
- 例:必要なデータファイルがパッケージに含まれてなく、しかもネットワークからダウンロードする方法が記されていない。
- 例: apt install しなくちゃならないパッケージの情報が不足している。
whl ファイルをpypiに登録しよう
コミュニティーにアナウンスする
- このモジュールを使いたいと思う人がいそうなところで、そのモジュールを作ったことをアナウンスする。
ドキュメントーションの作成
-
PyPIパッケージ公開手順
setup.py setup.cfg 時代の書き方での説明です。pyproject.toml 時代にあわせて、適宜読み替えるのが必要でしょう。 -
Python Packaging User Guide How to modernize a setup.py based project?