miseはmise.tomlファイルのあるディレクトリあるいはそのサブディレクトリへ移動すると、mise.tomlファイル内の定義が使用される。
その際、Pythonのvenvを作る仕組みも用意されており、以下の手順を定義ファイルだけで実現できる。
公式のドキュメントはこの辺り。
最小限の内容としては以下の通り。
[tools]
python = "3.12.2"
[env]
_.python.venv = { path = ".venv", create = true, python_create_args = ["--upgrade-deps"] }
PROJECT_NAME = "{{ config_root | basename }}"
[tasks.prerequisites]
description = "Install dependencies"
alias = "i"
run = "pip install -r requirements.txt"
これが~/local/src/work-app/mise.tomlにあるとして、以下のようにディレクトリ移動すると自動でvenvが有効になりインタプリタが切り替わるのがわかる。
zaki@cloud-dev2:~$ python --version Python 3.12.8 zaki@cloud-dev2:~$ cd local/src/work-app/ (work-app) zaki@cloud-dev2:~/local/src/work-app$ python --version Python 3.12.2 (work-app) zaki@cloud-dev2:~/local/src/work-app$ which python ~/local/src/work-app/.venv/bin/python (work-app) zaki@cloud-dev2:~/local/src/work-app$ python -c "import site;print(site.getsitepackages())" ['/home/zaki/local/src/work-app/.venv/lib/python3.12/site-packages'] (work-app) zaki@cloud-dev2:~/local/src/work-app$
以下、ざっくり解説
venvの作成
公式のAutomatic virtualenv activationに載っている。
[env]
_.python.venv = { path = ".venv", create = true, python_create_args = ["--upgrade-deps"] }
最低限「_.python.venv = { path = ".venv", create = true }」だけあれば「指定ディレクトリに移動した時点でvenv有効/なければ作成」を実現できるが、pip自体がアップデートされないままなのでpython_create_args = ["--upgrade-deps"]も付与している。
これがあれば python -m venv .venv --upgrade-deps 相当の動作になる。
ディレクトリを別の場所にしたい場合はpathの内容を変更する。
Pythonインタプリタバージョンの指定
[tools] python = "3.12.2"
上記で対象ディレクトリ移動時にインタプリタバージョンが3.12.2に自動でセットされる(mise use python@3.12.2相当)
ただしローカルに未インストールの場合は自動インストールはされず、下記警告が表示されvenvの作成も行われない。
$ cd ~/local/src/work-app mise WARN no venv found at: ~/local/src/work-app/.venv mise will automatically create the venv once all requested python versions are installed. To install the missing python versions and create the venv, please run: mise install mise WARN missing: python@3.12.2
この時はメッセージの通りmise installを実行すれば、指定バージョンのPythonインタプリタがインストールされ、venvも作成される。
$ mise install [notice] A new release of pip is available: 24.0 -> 25.1.1 [notice] To update, run: /home/zaki/.local/share/mise/installs/python/3.12.2/bin/python -m pip install --upgrade pip mise python@3.12.2 ✓ installed mise creating venv with stdlib at: ~/local/src/work-app/.venv
venv名プロンプト
標準のvenv環境は、アクティべートすればプロンプトにvenv名が表示されるが、あいにくmiseのvenv有効化機能ではこの処理が行われない。
(手動でbin/activateを実行すれば通常通りプロンプトは更新されるけど)
[env]部分で環境変数をセットできてPS1も更新できるのだが、ディレクトリを抜けたときに既存状態を復元できなかったりあまりスマートに変更できないので、$HOME/.bashrcの標準のPS1環境変数との組み合わせの小細工で実現は可能。
[env]
PROJECT_NAME = "{{ config_root | basename }}"
この部分でPROJECT_NAME環境変数にディレクトリ名をセットしている。
これを使って$HOME/.bashrcのPS1環境変数を以下のように定義。
_venv_prompt() {
if [ -z "$VIRTUAL_ENV_PROMPT" ] && [ -n "$VIRTUAL_ENV" ];then
local prompt
if [ -n "$PROJECT_NAME" ];then
prompt=$PROJECT_NAME
fi
printf '(%s) ' "$prompt"
fi
}
PS1='$(_venv_prompt)'$PS1
これで、miseで管理されたvenvが有効になるとPROJECT_NAME環境変数を参照してプロンプトを更新する。
zaki@cloud-dev2:~$ cd local/src/work-app/ (work-app) zaki@cloud-dev2:~/local/src/work-app$
uvを使ってる場合は以下の記事を参考。
環境変数の追加
上記のPROJECT_NAMEの通り、環境変数をプロジェクトのディレクトリ以下のみ有効にすることができる。
例えば追加のAnsibleコレクションを対象ディレクトリ以下にインストールしたければ、
[env]
ANSIBLE_COLLECTIONS_PATH = "{{ config_root }}/.ansible"
のように書けばプロジェクトのディレクトリ直下の.ansible/ディレクトリ以下へインストールされる。
タスクランナーでpipパッケージのインストール
pipパッケージのインストールも(venv作成とセットで)完全自動化したかったけど、これはよくわからなかったというかうまくいかなかったので、pip install -r requirements.txtを実行する。
ただそれだと手動感が強いので、miseのタスクランナーを使ってインストールする。
そもそも公式ドキュメントでもタスクランナー使ってrequirements.txtをpip install起動してるので現バージョンはこのやり方がべスプラかもしれない。
A Python Project with virtualenv
[tasks.prerequisites] description = "Install prerequisites" alias = "i" run = "pip install -r requirements.txt"
この定義がある状態でmise runを実行すると、定義してあるタスク一覧が表示される。
$ mise run Tasks Select a task to run ❯ prerequisites Install prerequisites / esc clear filter • enter confirm
その中から(例が悪くてタスクが1個しかないので選択の余地がないけど)prerequisitesを上下で選択してenter押下で、runに記述したpip install -r requirements.txtが起動する。
(aliasの設定があるので、キーボード選択でなくi押下でも起動する)
Tasks prerequisites [prerequisites] $ pip install -r requirements.txt Collecting pyyaml==6.0.2 (from -r requirements.txt (line 1)) Using cached PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.1 kB) Using cached PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (767 kB) Installing collected packages: pyyaml Successfully installed pyyaml-6.0.2
これでrequirements.txtに記載した必要パッケージがインストールされる。
なお、runには複数行の定義もできるので、以下のようにAnsible環境のセットアップみたいなことも可能
run = """ pip install -r requirements.txt ansible-galaxy collection install -r requirements.yml """
タスクランナーについては、以下の記事が動画があるのでインタラクティブ感がわかりやすい。
MISE_PYTHON_DEFAULT_PACKAGES_FILE 変数を使ったパッケージインストール
Default Python packagesに、「$HOME/.default-python-packagesあるいはMISE_PYTHON_DEFAULT_PACKAGES_FILE変数にデフォルトパッケージ一覧を書いたファイル(requirements.txt相当)をセットしておくと自動でパッケージインストールする」とあるが、これはvenv作成時でなく、Pythonインタプリタのインストールのタイミングで処理されるため、今回は見送り。
(しかもvenvでなくPythonインタプリタのインストールディレクトリ側に入るので、vevnが有効になると参照できない)
参考
miseはちょっと前から使っていたけど、タスクランナーの存在を知らず単にパッケージ管理ツールとしてのみだった。
引数の多いコマンドの実行などはシェルスクリプトやエイリアスにして$HOME/.bashrcとかに定義しておけば個人環境では解決するけど複数人で同じことをやろうとする場合はタスクランナーは間違いが少なくて良さそう。TUIなんでCLIが苦手な人も使えるんで「作業手順書」も簡潔な内容になることが期待できそう。
あとは公式でもuvを使った構築を解説してるが、まだ自分がuvに手を出してないのでそのうち。。