以前書いたpipx runのtipsを補足します。
% PYTHONINSPECT=1 pipx run ./script.py >>>
目次
- 目次
- Pythonスクリプトをpipx runで実行した後に対話モードに入るには、PYTHONINSPECT環境変数を指定する
- pipx runは仮想環境を作る
- 実装はsubprocess.runで仮想環境を作る
- 再現実験
- まとめ:pipx runと環境変数PYTHONINSPECT
Pythonスクリプトをpipx runで実行した後に対話モードに入るには、PYTHONINSPECT環境変数を指定する
pipx runにpython -i相当の動きをさせるために、環境変数PYTHONINSPECTを指定する方法を見出しました。
https://docs.python.org/ja/3/using/cmdline.html#envvar-PYTHONINSPECT
pipx runのプロセスが変わってpythonとなるのですが、環境変数PYTHONINSPECTも渡ることで、対話モードに入ります。
味をしめて使っていく中で、PYTHONINSPECT=1 pipx runがハングする事象に気づいたのです。
pipx runは仮想環境を作る
pipx runの動きを観察すると以下のようでした1
- 仮想環境を作る
- 仮想環境に依存ライブラリをインストール
- 仮想環境でスクリプトを実行
毎回1-3を行うわけではなく、1の仮想環境は一定期間キャッシュするようです。
Download the latest version of a package to a temporary virtual environment, then run an app from it.
The environment will be cached and re-used for up to 14 days. (pipx run --helpより)
すでにある仮想環境を使わないオプションが--no-cache
Do not reuse cached virtual environment if it exists
実装はsubprocess.runで仮想環境を作る
上記の1の箇所の実装なのですが、subprocess.runでpythonを呼び出しています
pipx runにてvenv.create_venv(venv_args, pip_args)
https://github.com/pypa/pipx/blob/1.6.0/src/pipx/commands/run.py#L101
create_venv()メソッドの実装
https://github.com/pypa/pipx/blob/1.6.0/src/pipx/venv.py#L158
# 関数の中から抜粋しています cmd = [self.python, "-m", "venv"] venv_process = run_subprocess(cmd + venv_args + [str(self.root)], run_dir=str(self.root))
cmdは言ってしまえばpython -m venv .venvのようなものです。
ここにPYTHONINSPECT=1が副作用をもたらします。
仮想環境を作ったプロセスが対話モードに入ってしまう(と思われる)ので、pipx runは仮想環境作成中の表示でハングします。

再現実験
% pipx --version 1.6.0
pipx runのように、別プロセスでpython -m venvを呼び出して仮想環境を作るプログラムを用意しました。
import subprocess result = subprocess.run(["python", "-m", "venv", ".venv"]) print(f"{result.returncode=}")
(出来上がる仮想環境は都度消しています)
通常の実行
% python reproduce.py result.returncode=0
python -iはスクリプトが流れた後に対話モードに入ります(ハングしません)
% python -i reproduce.py result.returncode=0 >>>
ハングするケースです
% PYTHONINSPECT=1 python reproduce.py
別のターミナルでpsすると、python -m venv .venvのプロセスがあります。
nikkie 13556 0.0 0.0 410967856 15456 s000 S+ 1:47AM 0:00.03 python -m venv .venv
これをkillすると、スクリプト実行中のターミナルは対話モードに入ります。
(killにより、スクリプトを実行しているpythonプロセスに返ってきて、-iが効いた)
% PYTHONINSPECT=1 python reproduce.py result.returncode=-15 >>>
まとめ:pipx runと環境変数PYTHONINSPECT
pipxが管理する仮想環境の状態に思いを馳せないといけないのがあまり好みではないのですが2、以下の流れになると思います。
- inline script metadataだけ書いて
pipx runしてしまう- ここで仮想環境の作成が完了する想定
- 以降は、
PYTHONINSPECT=1 pipx runで対話モードを駆使しながらサクサク開発- キャッシュされた仮想環境を使っており、新規に作ることはないのでワークする
ただし、pipx run --no-cacheするときは(新たな仮想環境を作るので)PYTHONINSPECTは指定しない
以上、pipx runを使っていてPYTHONINSPECT環境変数指定のためにハングしてしまうことがある事象とその対処案の共有でした。