■ はじめに
https://dk521123.hatenablog.com/entry/2020/02/09/234350
で egg / wheel ファイルを作成したが、 今回は、Pythonのパッケージ配布で、ちょっと古い方法だが setup.pyによる作成方法について扱う ちなみに、この手の話は、結構、古いやり方とかあるので ちょっと混乱する。 別の方法は、以下の関連記事を参照のこと
パッケージ配布 ~ pyproject.tomlによる作成方法 ~
https://dk521123.hatenablog.com/entry/2024/03/28/000000
目次
【1】用語整理 1)setuptools 2)setup.py 【2】setup.pyを使った作成方法 1)ファイル構成 2)コマンドによるパッケージ作成 【3】使い方 1)インストール方法1:ファイルから pip install 2)インストール方法2:GitHubから pip install 3)アンインストール 【4】補足1:__init__.py の役割 1)「[2] インポートの制御のため」について 2)解決策「__all__」
【1】用語整理
1)setuptools
* Pythonパッケージするためのツール => 作成したモジュールを pip install でインストール可能になる
https://packaging.python.org/ja/latest/guides/distributing-packages-using-setuptools/
https://packaging.python.org/ja/latest/key_projects/#setuptools
2)setup.py
* パッケージのメタデータを定義
https://packaging.python.org/ja/latest/discussions/setup-py-deprecated/
より抜粋 ~~~~ setup.py は非推奨になりましたか? いいえ、 setup.py および Setuptools は非推奨にはなっていません。 ・・・略・・・ しかしながら、 python setup.py および setup.py を コマンドラインツールとして使うことは非推奨になりました。 ・・・略・・・ python setup.py install python setup.py develop python setup.py sdist python setup.py bdist_wheel
sdist
* ソースコードをtar.gz形式で配布
bdist_wheel
* ビルド済みのファイルをwheel形式で配布 => 以下の関連記事でも使用した
https://dk521123.hatenablog.com/entry/2020/02/09/234350
【2】setup.pyを使った作成方法
* 以下の「1)ファイル構成」で行う
1)ファイル構成
├─ hello_package # パッケージ │ ├─ world_sub_package # サブパッケージ(Options) │ │ ├─ __init__.py # ★今回は空ファイルでもいい。詳細は「補足1:__init__.py の役割」を参照 │ │ └─ world.py # サブモジュール │ ├─ __init__.py # ★今回は空ファイルでもいい。詳細は「補足1:__init__.py の役割」を参照 │ └─ hello.py # モジュール ├─ main.py # モジュール動作確認用プログラム(Options) └─ setup.py # プロジェクトの一番上(ルート)にある必要がある
setup.py
from setuptools import setup setup( # Package name name="hello_package", # Package version version="1.0.0", packages=[ "hello_package", "hello_package.world_sub_package" ], url="https://dk521123.hatenablog.com/", license="MIT", author="Your-name", author_email="your-email@xxx.com", description="This is just a sample" )
hello_package.hello.py
def say_hello(name): return f"Hello, {name}!!"
hello_package.world_sub_package.world.py
def say_world(): return "The World!!?"
main.py
import hello_package.hello from hello_package.world_sub_package import world result1 = hello_package.hello.say_hello("Mike") # The result from hello - Hello, {name}!! print(f"The result from hello - {result1}") result2 = world.say_world() # The result from world - The World!!? print(f"The result from world - {result2}")
2)コマンドによるパッケージ作成
に従って行うと、以下の成果物(パッケージ配布物)ができる ~~~~~ * dist/hello_package-1.0.0.tar.gz * dist/hello_package-1.0.0-py3-none-any.whl ~~~~~
コマンド例
# Step1: build パッケージをインストールする python -m pip install build # Step2: パッケージ作成 python -m build # 個別で作成したい場合 # python -m build --sdist # python -m build --wheel # 以下は、もう古いらしい。。。 # python setup.py sdist # python setup.py bdist_wheel
【3】使い方
1)インストール方法1:ファイルから pip install
# インストール pip install dist/hello_package-1.0.0.tar.gz # pip install dist/hello_package-1.0.0-py3-none-any.whl ・・・略・・・ Successfully built hello-package Successfully installed hello-package-1.0.0 ・・・略・・・ # 確認 pip list ・・・略・・・ hello_package 1.0.0 ・・・略・・・
2)インストール方法2:GitHubから pip install
* 「pip install git+<GithubRepositoryURL>」でインストール可能
コマンド例
# リポジトリ名とパッケージ名が同じ場合 pip install git+https://github.com/acc_name/pkg_name.git # リポジトリ名とパッケージ名が異なる場合 # =>「パッケージ名@」を「git+https://…….git」の前に付加 pip install pkg_name@git+https://github.com/acc_name/repo_name.git # 「@v1.0」のように末尾にバージョンやタグを付加することも可能 pip install git+https://github.com/acc_name/pkg_name.git@v1.0
3)アンインストール
pip uninstall --yes hello_package
【4】補足1:init.py の役割
* __init__.py の主な役割は、以下の通り。 [1] Pythonパッケージとして認識させるため [2] インポートの制御のため [3] パッケージの初期化 / パッケージ全体の設定 => 詳細は、以下のサイトを参照。
https://ya6mablog.com/how-to-use-init-py/
1)「[2] インポートの制御のため」について
例えば、以下のように変更すると、エラーになる * 同じパッケージ内にファイルを追加 * main.pyの import を「*」に変更
エラーになるフォルダ構成
hello_package.world_sub_package + world.py + world2.py << 追加し、同じメソッドを追加 main.py << 変更(『[エラー] main.py』を参照)
[エラー] main.py
import hello_package.hello # 「*」に変更するとエラーになる #from hello_package.world_sub_package import world from hello_package.world_sub_package import * result1 = hello_package.hello.say_hello("Mike") print(f"The result from hello {result1}") result2 = world.say_world() print(f"The result from world {result2}")
2)解決策「all」
* 以下のように
hello_package.world_sub_package.init.py
__all__ = ['hello', 'hello2']
参考文献
bdist/sdist
https://blog.n-t.jp/post/tech/python-wheel-bdist-sdist-pip/
setup.py
https://ya6mablog.com/how-to-use-setup-py/
関連記事
パッケージ配布 ~ setuptoolsあれこれ ~
https://dk521123.hatenablog.com/entry/2024/04/17/132415
パッケージ配布 ~ pyproject.tomlによる作成方法 ~
https://dk521123.hatenablog.com/entry/2024/03/28/000000
egg / wheel ファイルを作成する
https://dk521123.hatenablog.com/entry/2020/02/09/234350
パッケージ管理 ~ pip ~
https://dk521123.hatenablog.com/entry/2021/07/02/000000
オフライン環境下で pip install するには
https://dk521123.hatenablog.com/entry/2021/07/10/164833