0
0

pythonモジュールの完成度を高める

Last updated at Posted at 2024-09-08

役に立つ(と思っている)自作Pythonモジュールがある。
それが、業務で必ず使うモジュールだったり、再利用する頻度が高いなら、モジュールの完成度を高めていこう。

書く必要があるコードを書こう

  • 再利用する価値があるか。
    • 他の人も使いたいと思うか。
  • 既存の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行の文字数を記載しよう。
      例:
pyproject.toml
[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にPythonライブラリを登録した話

コミュニティーにアナウンスする

  • このモジュールを使いたいと思う人がいそうなところで、そのモジュールを作ったことをアナウンスする。

ドキュメントーションの作成


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0