はじめに
書類に、なりたい... nikkieです。
真珠星ちゃんの「養子縁組って……」くらいの衝撃の事実を、Pythonで知ってしまいました。
目次
pip installするとコマンドが生える
必ずではないですが、pip install
するとコマンドが使えるようになります。
pip install pytest
->pytest
pip install ruff
->ruff
pip install sphinx
->sphinx-build
やsphinx-quickstart
このコマンドの実体に迫ります。
動作環境は以下です。
- Python 3.12.8
- pip 24.3.1
仮想環境を作って、自作ライブラリ kojo-fan-art1 をインストールします。
% python3.12 -m venv .venv --upgrade-deps % source .venv/bin/activate (.venv) % python -m pip install kojo-fan-art
kojo-fan-artをインストールすると、kojo-day
コマンドが使えるようになります。
(.venv) % kojo-day kokoro {"kokoro": "Thursday"}
コマンドの実体
仮想環境を出てもこのコマンドを実行できます。
仮想環境から出ると仮想環境にPATHが通らなくなるので、仮想環境下にあるコマンドの実体を指定します。
(.venv) % deactivate % .venv/bin/kojo-day kokoro {"kokoro": "Thursday"}
この.venv/bin/kojo-day
は、ファイルです。
% ls -l .venv/bin/kojo-day -rwxr-xr-x 1 (ユーザ名) (グループ名) 271 12 22 20:31 .venv/bin/kojo-day
パーミッションは755ですね。
実行権限(x)が付いています。
ファイルということは中身を見てみると(cat .venv/bin/kojo-day
)
#!/.../.venv/bin/python # -*- coding: utf-8 -*- import re import sys from the_solitary_castle_in_the_mirror.__main__ import main if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(main())
テキストファイルでした(バイナリではなかった)。
Pythonなので、読める... 読めるぞ!
シバン
1行目のシバン(shebang)がポイントだと思います。
#!/.../.venv/bin/python
シバンまたはシェバン (英: shebang) とはUNIXのスクリプトの #! から始まる1行目のこと。起動してスクリプトを読み込むインタプリタを指定する。
起動してスクリプトを読み込むインタプリタを仮想環境のPythonに指定しています!
Python処理系がこのスクリプトを実行するわけです。
過去に書いた「pytest
とpython -m pytest
の何が違うのか」という記事を思い出しました(記事中はunko
コマンドで検証)
python -m unko
はsys.path
の先頭にカレントディレクトリを追加するunko
コマンドはsys.path
の先頭に.venv/bin
を追加している
後者のunko
コマンドでのsys.path
ですが、シバンで仮想環境のPython(.venv/bin/python
)を指定しているためかもしれません2
落穂拾い
正規表現は何?
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.argv[0]
を加工しているコード。
末尾に以下のパターンがあれば、それを空文字列に置き換えて削除しています
-script.pyw
- または、
.exe
pipx install
pipx install
で生えるコマンドでも同様でした。
% pipx --version 1.7.1 % pipx install kojo-fan-art % which kojo-day /.../.local/bin/kojo-day % ls -l $(which kojo-day) lrwxr-xr-x 1 (ユーザ名) (グループ名) 58 12 22 21:03 /.../.local/bin/kojo-day -> /.../.local/pipx/venvs/kojo-fan-art/bin/kojo-day % head -n1 /.../.local/pipx/venvs/kojo-fan-art/bin/kojo-day #!/.../.local/pipx/venvs/kojo-fan-art/bin/python
pipx run
やuvx
3も一時的ですが仮想環境にインストールしているので、同様の仕組みと思われます。
終わりに
Pythonパッケージをインストールして使えるようになるコマンドがなぜ動くのか、その理由が分かりました。
インストールしたPython処理系をシバンで指定しているのですね。
つまりコマンドを動かすとき、裏でPythonを動かしているわけです(だから「遅い」という指摘になり、コマンドのRust実装(酸化)が進むのか)
コマンドを生やすにはpyproject.toml
の[project.scripts]
を指定している4わけですが、この指定から今回見たファイルが作られる仕組みは
https://packaging.python.org/ja/latest/specifications/entry-points/#entry-points
pip (または console_scripts を認識する他のインストーラ) が配布物をインストールする際に、各エントリポイントのコマンドラインラッパを生成します。
ということのようです(こちらの方にも潜ってみたいな5)
- 誕生の秘密 ↩
- このあたりが関係するのではなかろうか ↩
-
uvx
、高機能ですごい! ↩ - 使ってみようpyproject.toml! projectの設定に使う項目のみんなを紹介するぜ!! - nikkie-ftnextの日記↩
- https://github.com/pypa/pip/blob/24.3.1/src/pip/_vendor/distlib/scripts.py#L40-L49↩