Python install manager 26.0で変わった「グローバルショートカット」を理解する:pipやblackが動くまでの流れHPかわさきの研究ノート

Python install managerはバージョン26.0でパッケージが提供するコマンドやスクリプトへのショートカットも生成するようになりました。その使い勝手や仕組みについて、今回は調べてみました。

» 2026年03月03日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「HPかわさきの研究ノート」のインデックス

連載目次


かわさき

 どうもHPかわさきです。

 『Windowsで「pipが通らない」を減らす Python install manager 26.0のグローバルショートカット』は読んでいただけましたか? 今回はグローバルショートカットについて、Python install manager 25.xと26.0との違いや、どんな仕組みでpipコマンドが使えるようになったのか、なんでパッケージのインストール時にはショートカットが生成されないのかなどについて調べてみました。


ざっくりとまとめると?

  • グローバルショートカットディレクトリはPython install manager 25.2でも作成される
  • でも、パッケージが提供するそこにコマンド群へのグローバルショートカットは生成されない
  • Python install manager 26.0ではそこが改善され、パッケージが提供するコマンドのグローバルショートカットが生成されるようになった
  • ただし、グローバルショートカットが生成されるのは「py install ……」を実行したタイミング
  • パッケージのインストールで、グローバルショートカットが生成されるわけではない
  • グローバルショートカットはPythonのentry_points.txtを利用したもの

グローバルショートカットとは

 『Windowsで「pipが通らない」を減らす Python install manager 26.0のグローバルショートカット』でも触れましたが、Python install manager 26.0ではインストール済みのパッケージに関して、それらのentry_points.txtファイルを参照し、パッケージが提供するコマンドやスクリプトをコマンドラインから起動できるようにする「グローバルショートカット」を生成するようになりました。

 筆者が試したところでは、グローバルショートカットは%LOCALAPPDATA%\Python\binディレクトリに作成されます(このディレクトリを以下ではグローバルショートカットディレクトリと呼びます)。

 このディレクトリ自体はPython install manager 25.0の時点でも作成されるようになっていました。Python install managerをインストールすると次のようにグローバルショートカットディレクトリを環境変数PATHに追加するかどうかが問い合わせられます(ただし、以下はバージョン25.2のもので、バージョン25.0でもそうだったかは確認できませんでした)。

グローバルショートカットディレクトリを環境変数PATHに追加するかどうかの確認 グローバルショートカットディレクトリを環境変数PATHに追加するかどうかの確認

 Python install manager 25.xではグローバルショートカットディレクトリには、Python処理系(Python 3.14、Python 3.13など)へのショートカットが置かれますが、パッケージが提供するコマンドやスクリプトへのショートカットは置かれません。「py install --refresh」コマンドでグローバルショートカットディレクトリを更新してもパッケージ由来のコマンドやスクリプトへのショートカットは生成されません。

 以下はPython install manager 25.2がインストールされた環境で、python3.14コマンド、pip3コマンドなどを実行しているところです(グローバルショートカットディレクトリは環境変数PATHに登録済み)。

バージョン25.xでは、python3.14コマンドはイケるが、pip3コマンドはイケない…… バージョン25.xでは、python3.14コマンドはイケるが、pip3コマンドはイケない……

 python3.14コマンドを実行すると、ちゃんと起動できます(グローバルショートカットディレクトリの名前を変更したら、python3.14コマンドを起動できなくなったので、これがこのディレクトリのおかげなことも確認済みです)。が、pip3コマンドを実行してもエラーになってしまいます。「py install --refresh」コマンドを実行してもダメなことが確認できました。

 このとき(Python install manager 25.2)のグローバルショートカットディレクトリの内容は次のようになっています。

グローバルショートカットディレクトリにはpipやpip3コマンドへのショートカットがない グローバルショートカットディレクトリにはpipやpip3コマンドへのショートカットがない

 なるほど。pip3コマンドがないことが分かります(後で、バージョン26でどうなっているかを見てもらいましょう)。

 これに対して、Python install manager 26.0ではどうかを確認したのが以下です。

バージョン26.0ではpip3も問題なくイケる バージョン26.0ではpip3も問題なくイケる

 ご覧の通り、python3.14コマンドもpip3コマンドも実行できました。グローバルショートカットディレクトリがどうなっているかというと以下のようになっていました。

pipコマンド、pip3コマンドへのショートカットがあることが分かる pipコマンド、pip3コマンドへのショートカットがあることが分かる

 このようにpipコマンドやpip3コマンドへのショートカットがあります。Python install manager 26ではこのようにpythonコマンドだけではなく、パッケージのインストール時に提供される各種のコマンドやスクリプトへのショートカットも作られるようになり、「グローバルな環境」(つまり、PCにインストールされたPython環境)にそのままパッケージをインストールする場合のパッケージ使用の利便性が向上しました。

パッケージをグローバルにインストールしてみる

 というわけで、グローバルにパッケージをインストールしてみます。ここではPythonのフォーマッタであるblackを例としました。以下はblackのインストール直後にblackコマンドを実行できるかどうかを試したものです。

「black ……」コマンドは起動できないが、「python -m black ……」なら大丈夫 「black ……」コマンドは起動できないが、「python -m black ……」なら大丈夫

 「black --version」コマンドを呼び出せません。が、「python -m black --version」コマンドなら大丈夫です。これがグローバルショートカットの自動生成の(現時点における)弱点です。つまり、pipによるパッケージのインストールとショートカットの生成が同期されないことです。

 ショートカットを生成するには「py install --refresh」コマンドを実行します。これにより、グローバルショートカットディレクトリが更新され、パッケージのインストール後、生成されていなかったショートカットが生成されます。

グローバルショートカットディレクトリが更新され「black --version」が実行できるようになった グローバルショートカットディレクトリが更新され「black --version」が実行できるようになった

 なんでこんなことになっているかというと、Python install manager 26.0でのグローバルショートカット生成はentry_points.txtファイルを頼りにしているからです。というわけで、ちょっとその辺についても見ておきましょう。

entry_points.txtファイル

 entry_points.txtファイルというのは、パッケージをインストールする際に同時にインストールされるメタデータファイルです(Python install managerでのみ使われるものではありません)。

 pipを例に取れば、pipのインストール後に「pip install ……」のようなコマンドラインを実行できるようにする、つまり各種コマンドを呼び出す「エントリポイント」を記述しているのがentry_points.txtファイルといえます。このファイルはPythonをインストールした先にある「Lib\site-packages\パッケージ-バージョン.dist-info」ディレクトリに作成されます(パッケージごとにentry_points.txtファイルが存在するということです)。


かわさき

 pip 25.3であれば、「Lib\site-packages\pip-25.3.dist-info」ディレクトリです。


 以下にpipのentry_points.txtの内容を示します。

pipのentry_points.txtファイルの内容 pipのentry_points.txtファイルの内容

 これはpip3コマンドとpipコマンドが呼び出されたら、pip._internal.cli.mainのmain関数でこれを処理することを意味しています。このmain関数では与えられた引数を基に「pip install」や「pip list」のようなコマンドを処理すると思ってください(詳細は省略します)。

 Python install managerは「py install」コマンドの実行時に、インストール済みのパッケージのdist-infoにあるentry_points.txtファイルを参照し、対応するショートカットを生成していると考えられます。


かわさき

 このような振る舞いをすることから(というか、Python install managerがパッケージのインストールの全てを監視しているわけにはいかないので)、インストーラーによるパッケージのインストールでは「py install --refresh」が必要になるのでしょう。

 『Python install manager 26.0』では「My hope is that one day installers (such as pip) will learn to run this command themselves, but until then, users will just have to get used to it」と述べられています。テキトーに訳すと「いつかはpipなどのインストーラーが「py install --refresh」を実行するようになってくれればいいけれど、それまではユーザーがそうすることに慣れるしかないねぇ」といったところでしょう。そういう日が来てくれるといいですね。


 では、実際に作成されるショートカットとはどんなものなのでしょう。実はグローバルショートカットディレクトリにある多くのEXEファイルはハードリンクとなっていて、同一のファイルです(pythonw系の実行ファイルはそれらで同一になっています)。

python3.exeやpip.exeは同一ファイルのハードリンク python3.exeやpip.exeは同一ファイルのハードリンク

 EXEファイル以外には、例えば、「python.exe.__target__」のようなファイルもあります。

たくさんの__target__ファイルがある たくさんの__target__ファイルがある

 __target__ファイルの中身は「%LOCALAPPDATA%\Python\pythoncore-バージョン\python.exe」のようになっています(ここでは環境変数LOCALAPPDATAを使っていますが、実際にはフルパス)。ビックリするのはpython.exe.__target__ファイルでもpip3.exe.__target__ファイルでも同じ内容になっていることです(pythonw系はそっちで同じ)。


かわさき

 「pythoncore-バージョン」には「pythoncore-3.14-64」などが入ります。これはおそらく、Python install managerによってインストールされるPythonを意味しています。どのバージョンをデフォルトとして使っているかによって、この値は変わるかもしれません。


 要するに、ハードリンクとなっているEXEファイルはいわゆる「shim」というヤツです(複数要素をつなぎ合わせる小さな実行ファイル)。実体は、__target__ファイルで参照されるPythonインタプリターに処理を引き渡すものです。

 では、どんな処理を引き渡すのかというと、「python」「python3.14」などを実行するのであれば、コマンドライン引数を含めて全てが__target__ファイルで参照されるインタプリターに渡されるのだと推測しています。では、「pip list」「pip3 install」「black --version」などが呼び出されたときにはどうなるのでしょう。

 そうした場合に重要になるのが以下に示す__script__.pyファイルです。

__script__.pyファイル __script__.pyファイル

 このときには、__target__ファイルで指定されるPythonインタプリターに「__script__.py」ファイルが渡されるのでしょう。ちなみにpip.exe.__script__.pyファイルの内容は次のようになっています。

import sys

# Clear sys.path[0] if it contains this script.
# Be careful to use the most compatible Python code possible.
try:
    if sys.path[0]:
        if sys.argv[0].startswith(sys.path[0]):
            sys.path[0] = ""
        else:
            open(sys.path[0] + "/" + sys.argv[0], "rb").close()
            sys.path[0] = ""
except OSError:
    pass
except AttributeError:
    pass
except IndexError:
    pass

# Replace argv[0] with our executable instead of the script name.
try:
    if sys.argv[0][-14:].upper() == ".__SCRIPT__.PY":
        sys.argv[0] = sys.argv[0][:-14]
        sys.orig_argv[0] = sys.argv[0]
except AttributeError:
    pass
except IndexError:
    pass

from pip._internal.cli.main import main
sys.exit(main())

pip.exe.__script__.pyファイル

 これはsys.pathとargvを調整し、pip._internal.cli.mainモジュールのmain関数を呼び出しています。先ほどのentry_points.txtに書かれていたエントリポイントが呼び出されるということですね。

 では、shimが__script__.pyファイルを呼び出して、そこからpip._internal.cli.main.main関数が呼び出されるというのがホントかどうかを試してみましょう。といっても、ここではpip.exe.__script__.pyファイルとpip._internal.cli.main.main関数の先頭に「print('hello from pip.exe.__script__.py')」と「print('hello from pip._internal.cli.main.main')」の2行を書き加えて「pip list」コマンドを実行するだけです。以下はその実行結果です。

pip.exe.__script__.pyファイルが呼び出され、そこからpip._internal.cli.main.main関数が呼び出されたことが分かる pip.exe.__script__.pyファイルが呼び出され、そこからpip._internal.cli.main.main関数が呼び出されたことが分かる

 というわけで、どうやらそのように動いているようです。


かわさき

 Python install manager 26.0はグローバルにインストールされているPythonの(パッケージの)使い勝手を改善してくれるツールということがよく分かりました。entry_points.txtについては、筆者も深掘りはできていませんが、これについては時間があればもうちょっと勉強したいところです。


「HPかわさきの研究ノート」のインデックス

HPかわさきの研究ノート

Copyright© Digital Advantage Corp. All Rights Reserved.

アイティメディアからのお知らせ

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2026
人に頼れない今こそ、本音で語るセキュリティ「モダナイズ」
4AI by @IT - AIを作り、動かし、守り、生かす
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。