このページでは、自作パッケージをインストールする方法をまとめます。
「pyproject.toml」と「pip」を使います。
個人やその周りで利用する場合を想定していて、PyPIなど不特定多数に公開するための作法は考慮していません。
参考ページ
Python のプロジェクトをパッケージングする — Python Packaging User Guide
使用した環境
WSL2 Ubuntu - 20.04
Python 3.10.0
pip 22.3
setup.pyとpyproject.toml
パッケージのインストールにはビルドをする必要があり、検索をかけると、主に、
- setup.py(+ setup.cfg)
- pyproject.toml
の二つのやり方が出てくると思います。
現時点では、PEP 518によって「pyproject.toml」を使う方が標準的な方法です。
ざっくりとした経緯は(私なりの理解ですが)、
- setup.pyを使った方法では依存関係が把握しづらかった。
- pipでsetup.pyを実行するにはsetuptoolsが必要だと仮定するようになった。
これでは他のビルドツールが盛り上がってきても貢献が難しく、他のツールの普及を妨げることになっている。 - それなら「pyproject.toml」でビルドツールを選択できるようにし、依存関係を書くようにしよう。
となっています。
ビルドツール
複数のビルドツールがあります。
各プロジェクト概要 — Python Packaging User Guide
最初「setuptools」を使うつもりだったのですが、今の段階(2022年10月)では「setuptools」での「pyproject.toml」による設定方法はベータ版の書き方もあり、簡単なパッケージ作成なら「hatch」が一番良さそうだったので、このページではこちら(注)を使います。
(注)実際にはhatchそのものではなく、そのバックエンドツールを使用します。
pyproject.tomlでの設定は大枠では共通していて、各ツールごとに使える機能は異なります。tomlの書き方を覚えておけば別のバックエンドツールに変更できます。
ビルドツール自体をインストールし、その手順に従ってビルドする方法もあります。
自作パッケージの用意
説明にあたって簡単なパッケージを作りました。
$ tree greeting greeting ├── goodbye.py ├── hello.py ├── __init__.py ├── text1.txt └── text2.txt 0 directories, 5 files
「greeting」が自作パッケージ。
「hello.py」と「goodbye.py」は、コード中に外部パッケージの「termcolor」をインポートしています。
from termcolor import cprint
def say():
cprint('Hello', 'red')
from termcolor import cprint
def say():
cprint('Goodbye', 'blue')
それぞれ色を付けてアイサツを表示する関数を定義しています。
「__init__.py」、「text1.txt」、「text2.txt」の中身は空です。
そのうち「text2.txt」はインストール対象から除外するつもりです。
pyproject.toml
パッケージと同じ場所に「pyproject.toml」を作成します。
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "greeting"
version = "1.0.0"
dependencies = ["termcolor"]
[tool.hatch.build]
exclude = ["text2.txt"]
[build-system]
requires――使うツールの名前を書きます。
上記ではhatchのバックエンドツールである”hatchling"を指定。
build-backend――バックエンドに使用するPythonオブジェクトの名前を書きます。
使いたいツールのWebページなどで確認。
[project]
name――パッケージに付ける名前。
パッケージをインポートするときの名前ではありません。
dependencies――必要な外部パッケージをここに書いておくと、インストール時に合わせて追加されます。
[project]内ではその他のメタデータが設定できます。
Declaring project metadata[PyPA]
Pythonのパッケージシステムに準拠しているツールなら、[build-system]や[project]などのテーブルが設定できるようになっています。
[tool.hatch.build]
exclude――除外したいファイルを指定します。
他のビルドツールにも似た機能はあるかもしれませんが、項目や設定方法が異なります。
$ tree mypkg mypkg ├── greeting │ ├── goodbye.py │ ├── hello.py │ ├── __init__.py │ ├── text1.txt │ └── text2.txt └── pyproject.toml 1 directory, 6 files
「mypkg」というディレクトリのなかに、パッケージとtomlファイルが入っています。
これ以降の項目は仮想環境を作成してから行っています。
環境を汚したくないならおすすめです。
配布物の作成
念のため、pipをアップグレードしてください。
pip install --upgrade pip
配布物にしておくと、持ち運びがしやすくなり、ディレクトリごとコピーして渡すより余計なものが入りこまなくて便利です。
配布物が必要ないならインストールの項目に進んでください。
つぎに外部パッケージ「build」をインストールします。
pip install build
$ pip list Package Version ---------- ------- build 0.8.0 packaging 21.3 pep517 0.13.0 pip 22.3 pyparsing 3.0.9 setuptools 57.4.0 tomli 2.0.1
バックエンドツール(今回の場合は”hatchling”)はpipなどのフロントエンドツールが一時的に仮想環境を作って自動でインストールしてくれるため、追加する必要はありません。
以下のコマンドを「pyproject.toml」があるディレクトリで実行すると、ビルドして配布物を作成します。
python -m build
mypkg$ python -m build * Creating venv isolated environment... * Installing packages in isolated environment... (hatchling) * Getting dependencies for sdist... * Building sdist... * Building wheel from sdist * Creating venv isolated environment... * Installing packages in isolated environment... (hatchling) * Getting dependencies for wheel... * Building wheel... Successfully built greeting-1.0.0.tar.gz and greeting-1.0.0-py2.py3-none-any.whl
「dist」というディレクトリのなかに、以下のファイルが作成されました。
- greeting-1.0.0.tar.gz
- greeting-1.0.0-py2.py3-none-any.whl
インストール
手元のパッケージ
手元にパッケージ(未ビルド)があるなら、tomlとパッケージの入っているディレクトリを指定して、インストールします。
「pip install ディレクトリのパス」を実行します。
$ pip install mypkg/ Processing ./mypkg Installing build dependencies ... done Getting requirements to build wheel ... done Preparing metadata (pyproject.toml) ... done 省略 Successfully installed greeting-1.0.0
$ pip list Package Version ---------- ------- greeting 1.0.0 pip 22.3 setuptools 57.4.0 termcolor 2.0.1
「greeting」と「termcolor」がインストールされました。
ビルド済み配布物
「whl」と「tar.gz」形式、どちらでも構いません。
「pip install ファイルパス」で指定して実行します。
$ pip install dist/greeting-1.0.0-py2.py3-none-any.whl Processing ./dist/greeting-1.0.0-py2.py3-none-any.whl Requirement already satisfied: termcolor in /home/fujino/venv/lib/python3.10/site-packages (from greeting==1.0.0) (2.0.1) Installing collected packages: greeting Successfully installed greeting-1.0.0
$ pip list Package Version ---------- ------- greeting 1.0.0 pip 22.3 setuptools 57.4.0 termcolor 2.0.1
こちらも「greeting」と必要な「termcolor」が追加されました。
検証
自作のパッケージがどこにインストールされたか確認してみましょう。
$ pip show greeting Name: greeting Version: 1.0.0 Summary: Home-page: Author: Author-email: License: Location: /home/fujino/venv/lib/python3.10/site-packages Requires: termcolor Required-by:
環境によって異なると思いますが「site-packages」でした。
その「site-packages」内には「greeting」があり、中を確認すると、
site-packages$ tree greeting greeting ├── goodbye.py ├── hello.py ├── __init__.py ├── __pycache__ │ ├── goodbye.cpython-310.pyc │ ├── hello.cpython-310.pyc │ └── __init__.cpython-310.pyc └── text1.txt 1 directory, 7 files
「text2.txt」は入っていません。
「pyproject.toml」内で除外していたため、ですね。
今度はパッケージ内のモジュールが呼べるか確かめます。
まったく別のディレクトリに移動し、Pythonを対話モードで起動します。
$ cd $ pwd /home/fujino $ python Python 3.10.0 (default, Oct 12 2021, 16:02:08) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from greeting import hello, goodbye >>> hello.say() Hello >>> goodbye.say() Goodbye
helloモジュール、goodbyeモジュール、ともにインポートできました。
どこからでも呼べるようになり、これで利便性が上がりました。