はじめに
3月のPython Monthly Topicsを読んでいたnikkie氏。
「パッケージのインストールでpip install
とuv pip install
の処理時間を比較している。あれ、--no-cache
?」
$ time pip install pandas --no-cache $ time uv pip install pandas --no-cache
「pip install
に、私の知らないオプションがある...!」(※--no-cache
のこと)
目次
pip installのオプションに--no-cacheなんてあったっけ?
ドキュメント
pip installのドキュメントを見てみましょう。
https://pip.pypa.io/en/stable/cli/pip_install/#options
--no-
で始まるオプションはいくつかありますが、--no-cache
はヒットしません。
コマンドラインで--help
を渡します。
pip install --help
でもpip --help
でも「General Options」として--no-cache-dir
が出てきます
--no-cache-dir Disable the cache.
pipのドキュメントではここにあります1。
https://pip.pypa.io/en/stable/cli/pip/#general-options
ヘルプメッセージやドキュメントには--no-cache
というオプションは記載がないのですが、Python Monthly Topicsのpip install --no-cache
というコマンドは手元で動作しています。
なぜなんでしょう?
実装
pipのリポジトリを検索して見つけたのがこちら。
https://github.com/pypa/pip/blob/24.0/src/pip/_internal/cli/cmdoptions.py#L717-L724
no_cache: Callable[..., Option] = partial( Option, "--no-cache-dir", dest="cache_dir", action="callback", callback=_handle_no_cache_dir, help="Disable the cache.", )
この箇所は、functools.partialを使って、optparse.Optionの一部の引数を部分適用しています。
--no-cache
というオプションはなさそうでした。
なぜ--no-cache
と指定できるかを考えていて思い出したのは、argparseの例。
https://docs.python.org/ja/3/library/argparse.html#prefix-matching
parse_args() メソッドは、デフォルトで、長いオプションに曖昧さがない (先頭文字列が一意である) かぎり、先頭文字列に短縮して指定できます:
-bacon
オプションを-bac
と指定する例があります。
pipの実装に使われているoptparseは
バージョン 3.2 で非推奨: optparse モジュールは廃止予定であり、これ以上の開発は行われません。argparse モジュールを使用してください。
という存在ですが、optparseでも引数の短縮形はサポートされている記載がありました!
https://docs.python.org/ja/3/library/optparse.html#how-callbacks-are-called
opt_strのところ。
例えば、ユーザが --foobar の短縮形として --foo をコマンドラインに入力した時には、opt_str は "--foobar" となります。
どうやらpipの--no-cache-dir
オプションを短縮して、--no-cache
と書いていた(書けていた)のではないかと思われます。
--no-cache-dirを短縮できることを検証
optparseで検証プログラムを書いてみます2。
>>> options # --no-cache-dirと指定 <Values at 0x102402550: {'no_cache_dir': True}> >>> options2 # --no-cacheと短縮して指定 <Values at 0x102402790: {'no_cache_dir': True}>
短縮して指定できることが確認できました。
終わりに
pip install --no-cache
は私の知らないオプションではありませんでした。
--no-cache-dir
の短縮で、optparseやargparseでサポートされています(標準ライブラリ以外に関しては未調査です)。
短縮できる便利さはありつつも、個人的には--no-cache-dir
と短縮せずに使っていきたいですね。
「--no-cache
とも--no-cache-dir
とも指定できるのはなぜ?」と混乱の元になりますし、--no-cache
の情報はググラビリティが低めでした。
The Zen of Pythonにも「Explicit is better than implicit.」とありますし。
P.S. uv pip install
では?
% uv --version uv 0.1.31
uv --help
と打つと
-n, --no-cache Avoid reading from or writing to the cache
おそらくここ
https://github.com/astral-sh/uv/blob/0.1.31/crates/uv-cache/src/cli.rs#L10-L28
alias = "no-cache-dir"
とあるので、--no-cache
と--no-cache-dir
(の2つ)をサポートしていそうです。
% uv pip install pandas --no-cache-dir
pipの実装は短縮ができるので、--no-cache-d
もいけます(実際にやるかはおいておいて)。
ところがuvは上記の二者択一です。--no-cache-d
はサポートされません。
% uv pip install pandas --no-cache-d error: unexpected argument '--no-cache-d' found tip: a similar argument exists: '--no-cache-dir'
めちゃめちゃ重箱の隅ですけど、uvのオプションの指定の実装はpipと完全互換とは言えないのですね。
- 直リンク https://pip.pypa.io/en/stable/cli/pip/#cmdoption-no-cache-dir↩
-
parse_args
にはデフォルトでsys.argv[1:]
が渡ります https://docs.python.org/ja/3/library/optparse.html#optparse.OptionParser.parse_args 。コマンドラインで何回も実行して検証するのは少し手間なので、プログラム中で引数を渡すことにしました↩