プログラムでおかえしできるかな

定年を過ぎて何かの役に立てないかなと始めた元SEのブログです

自作ライブラリをコピーせずpipして使えるようにする方法【Python】

このエントリーをはてなブックマークに追加

プログラムをたくさん作ってくると共通に使用するライブラリもできてきます。
ライブラリを使う際、初めはモジュール(py ファイル)をコピーしていました。
コピーするとライブラリに変更が必要な場合にソースを二重管理することになってしまいます。

これらはライブラリを pip でインストール可能にすることで改善されます。

そのためにはライブラリとなるモジュールをパッケージ化します。

ここでは、そのパッケージング方法を紹介します。

目次

◆パッケージング

ライブラリを pip でインストールできるようにするには、パッケージ化が必要です。
パッケージ化するためにはモジュールを配置するフォルダ構成をパッケージ化の仕様に合わせた構成にする必要があります。
更に pyproject.toml ファイルを作成して、インストール情報を設定します。

▶モジュール、パッケージ、インポート

モジュール
 関数やクラスなどをまとめて書いた PY ファイル

パッケージ
 モジュールと __init__.py を含むフォルダ
__init__.py には初期化コードを記述しますが、空でも OK です。

※Python3.3以降では、__init__.py を含まないフォルダもパッケージとしてインポートできるようになりました。
名前空間パッケージと呼びます。 1 ここでは使っていません。

インポート
パッケージ化されたモジュールは、pip install でインストール後、インポートして使います。
import にはいろいろな使い方がありますが、__init__.py が空の場合は次のような使い方になります。

  • 【構文】from <パッケージ名> import <モジュール名>
  • 【構文】import <パッケージ名>.<モジュール名>
  • 【構文】from <パッケージ名>.<モジュール名> import <クラス名>

as を使うとモジュールなどに別名をつけてインポートできます。
 例:from <パッケージ名> import <モジュール名> as <別名>
 別名をつけた場合、元の名前は使えなくなります。

※次節のフォルダ構成でパッケージ化したモジュールのインポート例
from voice_juu7g import voice_input_GSR

※pip でのインストールはこちら:pipでパッケージをインストール ⤵

▶フォルダ構成

パッケージ化する場合のフォルダ構成の例を示します。

voice というプロジェクトフォルダに voice_juu7g というパッケージフォルダを含む場合を例にして示します。

プロジェクトフォルダ名とパッケージフォルダ名は、本来、同じ名前の方が使い易いとのことですがここでは分けています。(分けた理由は注意に示しました)

プロジェクトフォルダ名は、pip でインストールする時のパスとして使用します。
パッケージフォルダ名は、ソースで import する時のパッケージ名として使用します。

▽フォルダ構成

   📁voice                       # プロジェクトフォルダ(pip で指定)
    ├─📁voice_juu7g              # パッケージフォルダ(import で指定)
    │ ├──voice_input_GSR.py     # モジュール
    │ └──__init__.py           # パッケージとして扱う印
    ├─📁.vnev_voice              # 仮想環境フォルダ
    ├──pyproject.toml            # パッケージ設定ファイル(pip 可能な印)
    ├──README.md                 # 説明
    └──LICENSE                   # ライセンス

【注意】

  • src フォルダを推奨するものもありますが、ここでは使っていません
  • pyproject.toml ファイルは、BOM 無し UTF-8 で保存します
    BOM 付だと pip install でエラーになります
  • パッケージフォルダ名にはユーザ名を付加しています
    理由は、GitHub からインストールできるようにした場合にパッケージ名が重複しないようにするためです
  • パッケージ名に _- を用いないのが推奨されていますが、
    ユーザー名を付加する場合、分かりにくいので付けています
    ただし、- はインポートでエラーになるので _ を使用しています
  • .venv_voice フォルダは仮想環境用のフォルダです。参考に表示しています
  • README.mdLICENSE ファイルはなくてもパッケージ化には影響ありません
    GitHubリポジトリを作成する場合やパッケージを配布する場合にあった方が良いので載せています

▶pyproject.tomlファイル

以前はパッケージ化する場合に setup.py ファイルを作成しました。
現在は代わりに pyproject.toml ファイルの使用が推奨されています。
pyproject.toml は、PEP518 として採択されています。

pyproject.toml には、パッケージを作成するビルドツールを指定する [build-system] テーブルが必要です。 2
ビルドツールには、flit、hatch、poetry、setuptools があります。
以前は setuptools が主流でしたが、pyproject.toml 対応で hatch が使い易いようです。
Python のドキュメントの使用例にも hatch が使われています。
また、hatch はビルド後にフォルダが残らないのでうれしいです。

前述のフォルダ構成に合わせたサンプルを以下に示します。

▽pyproject.toml ファイルの例

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "voice_juu7g"
version = "1.0.0"
authors = [  { name="juu7g" },]
description = "Voice recognition"
license = {text = "MIT License"}
requires-python = ">=3.8.5"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    ]
dependencies = [
    "PyAudio", "SpeechRecognition"
    ]
  • [build-system]:ビルドシステムの設定
    • requires:ビルドするために必要となるパッケージ群を列挙
    • build-backend:フロントエンドがビルドを実行するのに使用する Python オブジェクトの名前
  • [project]:プロジェクトのメタデータ

▶pyproject.tomlの[project]テーブルのキー

プロジェクトのメタデータについて一部をキーごとに表にします。

項目 キー 説明 記述例
テーブル [project]
名称 name ASCII 文字・数字・ピリオド・アンダースコア・ハイフンだけで構成
pip で認識される名前
name = "spam"
バージョン version PEP440で記述 version = "2020.0.0"
説明 description プロジェクトを要約する記述 description = "Lovely Spam! Wonderful Spam!"
readme readme プロジェクトの説明全体
(文字列(ファイルの位置(pyproject.tomlからの相対パス))かテーブル)
readme = "README.md"
readme = {file = "README.txt", content-type = "text/markdown"}
requires-python requires-python プロジェクトが要求するPythonのバージョン requires-python = ">=3.8"
ライセンス license fileまたはtextで指定
※textがシンプル
license = {file = "LICENSE"}
license = {text = "MIT License"}
著者 authors name と email のふたつのキーを伴ったテーブルの配列 authors = [ {name = "Pradyun Gedam", email = "pradyun@example.com"}, {name = "Another person"}, {email = "different.person@example.com"},]
保守者 maintainers 著者と同様
分類詞 classifiers Trove 分類子
(PyPIで使用される分類詞)
classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python"]
依存関係 dependencies プロジェクトの依存関係
不足していればインストールされる
dependencies = ["PyAudio", "SpeechRecognition"]

※ライセンスの指定は、file にすると pip show で表示した時にファイルの中身が出て見にくい

◆pipでパッケージをインストール

インストール可能なフォルダ構成に従ったパッケージは、pip コマンドでインストールできます。

pip コマンドは、優先的にネット上の PyPI サイトに公開されているものが対象になります。
その他にローカルにあるパッケージ、GitHub にあるパッケージを対象にすることもできます。

▶ローカルにあるパッケージをインストール

  • 【構文】pip install [パッケージのパス(フォルダ)]
  • よく使う使い方(サンプル)
    【構文】pip install -e c:\myprot\testpkg
  • 前節の例
    pip install -e voice
  • 引数
    • パッケージのパス(フォルダ):pyproject.toml ファイルが含まれたフォルダを指定
    • -e:エディタブルモード

★エディタブルモード(editable mode)

pip でのインストールには editable mode というモードが用意されています。
これはパッケージ開発時に便利な機能で、コードが編集可能な状態でパッケージをインストールできるものです。
editable mode でインストールされたパッケージのコードに変更を加えると、再インストールをしなくてもそのまま実行環境に反映されます。
editable mode を有効にするには -e ( --editable )オプションを使用します。

GitHub リポジトリにあるパッケージをインストール

更に、パッケージ化されたライブラリは、そのフォルダ構成のまま GitHubリポジトリとして公開すれば、Github からライブラリを pip でインストールが可能になります。

自分だけでなく他の人にも使い易くなります。

  • 【構文】pip install git+[リポジトリ URL]
  • よく使う使い方(サンプル)
    • pip install git+https://github.com/user/repository.git
    • pip install git+https://github.com/user/repository.git@main    # ブランチ指定
    • pip install git+https://github.com/user/repository.git@v2.18.4  # タグ指定
  • 前節の例
    pip install git+https://github.com/juu7g/test.git

GitHubリポジトリのページの「Code▼」を開くとクローン用URLが取得できます。
 そのURLは「リポジトリ名.git」となっています。

リポジトリの構成がフォルダ構成と同じであることが見て取れます

◎プライベートリポジトリの参照

プライベート設定にしているリポジトリからインストールしたい場合、トークンを使用して pip しなければなりません。

しかし、GitHubに接続するアプリなどで認証にPATを使用している場合、資格情報がWindowsに保存されているので、トークンを指定しなくてもインストールできます。

▶pip コマンドの使い方

pip コマンドの主な使い方を表にします。

機能 コマンド 備考
インストール pip install パッケージ名 ダウンロードしてインストール
アンインストール pip uninstall パッケージ名
更新 pip install -U パッケージ名 -U または --upgrade
インストール済みライブラリの確認 pip list
新しいバージョンの有無確認 pip list --outdated
バージョン指定のインストール pip install パッケージ名==バージョン 既にインストール済みなら
アンインストール後にインストール
インストール可能なバージョン表示 pip install パッケージ名== インストールがエラーになるが
インストール可能なバージョンを列挙
ローカルからインストール pip install -e パス -e または --editable
更新モード
基のソースを変更すると反映される
依存するライブラリの確認 pip show パッケージ名 パッケージの情報表示
ヘルプ pip -h pipについてのヘルプ
ヘルプ(install) pip install -h install 機能についてのヘルプ

◆さいごに

自分で作成したプログラムを自分で利用することがありました。
はじめはコピーして使っていました。

新しいプログラムを作る時は、いつも仮想環境を新しくして作っています。
そうすると利用したいプログラムのソースをコピーするだけでなく、そこで使用したライブラリもインストールし直さなければなりません。

なかなか面倒で、全部一度にできないかなと調べて今回のパッケージングにたどり着きました。
まだ、始めたばかりですが、なかなか快適です。

利用するライブラリは GitHub に公開しています。
パッケージングにより、PyPI に登録(そこまで使われるものでもないので)しなくても GitHub から pip でインストールできることもわかりました。

まだ、リポジトリのパッケージ対応はできていませんが、徐々に進めて行こうと思います。
そうすれば、利用される方に楽に使っていただけるはずなので。

あわせて読みたい 📖 音声入力で文章作成するアプリの作り方【Python】 🔗

◇ご注意

本記事は次のバージョンの下で動作した内容を基に記述しています。

◇免責事項

ご利用に際しては、『免責事項』をご確認ください。
お気づきの点がございましたら『お問い合わせ』からお問い合わせください。

◆参考

投稿:

  1. 名前空間パッケージ:名前空間パッケージをパッケージする — Python Packaging User Guide
  2. Python のマニュアルでは必要とありますが、PEP 518 では無い場合のデフォルトが示されています。
    デフォルトは、 requires = ["setuptools", "wheel"] です。