以前書いた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
環境変数指定のためにハングしてしまうことがある事象とその対処案の共有でした。