このページについて
nixを使ってみようかなーと思っていたところ、nixとuvを結合するuv2nixというツールがあるのを知り、NotebookLMでまとめてみました。
この文章はNotebookLMによって生成されました。
ライセンスについて
[1]のライセンスがCC BY 4.0であることに基づき、この文章もCC BY 4.0でライセンスされています。
- 参照:
- [1] NixCon 2025 - Python packaging with nixpkgs, pyproject.nix & uv2nix - YouTube
- ライセンス: CC BY 4.0
- [2] Getting started - uv2nix
- [1] NixCon 2025 - Python packaging with nixpkgs, pyproject.nix & uv2nix - YouTube
NixとPythonパッケージ管理:uv2nixとflake.nixの役割
1. なぜ flake.nix (Nixpkgs) だけで管理しないのか
従来のNixpkgsを使用したPython開発(flake.nixのみでの管理)には、主に以下の技術的・実用的な課題が存在します。
-
二重管理と非効率性: Python標準の
pyproject.tomlがあるにもかかわらず、その内容(依存関係)をflake.nix内のwithPackages引数として手動で翻訳・記述する必要があり、非効率(unergonomic)です,。 - 開発ツールの非互換性: Nixpkgsは標準的な仮想環境(virtual environment / venv)を作成しません。その結果、標準的なvenvの存在を前提とするLSP(例: Pyright)やエディタの補完機能が正常に動作しない場合があります。
- バージョンの制約: Nixpkgsに収録されているPythonパッケージセットのバージョン(例: Jinja2 3.1.5)が強制されるため、プロジェクトが要求する特定のバージョン(例: 3.1.6)と不整合が生じることがあります,。
-
環境変数による汚染(Footguns): NixpkgsのPython環境は
PYTHONPATHを使用して依存関係を伝播させます。これにより、開発環境に入った際、Nixpkgs側の依存関係が優先されてしまい、意図しないライブラリが読み込まれる問題が発生します,。
2. uv2nix とは
uv2nix は、Rust製の高速なPythonパッケージマネージャ uv のワークスペースを取り込み、純粋なNixコード(Pure Nix code)を使用して動的にNixのDerivation(ビルド定義)を生成するツールです。
-
PyPIからの直接構築: NixpkgsのPythonパッケージセットに依存せず、
uv.lockファイルに基づいてPyPIから直接ソースやバイナリ(Wheel)を取得し、環境を構築します。 - 標準的な仮想環境の提供: Nix独自の環境構造ではなく、標準的な仮想環境(bog-standard virtual environment)を作成するため、LSPなどの既存のPython開発ツールがそのまま動作します。
- ワークスペースとEditableインストール: 複数のパッケージを含むワークスペースや、開発中のローカルパッケージのEditableインストール(編集可能モード)に対応しており、スクリプトなどがパスに通った状態で開発できます,。
-
基盤技術:
pyproject.nixライブラリとそのビルドインフラストラクチャをベースに構築されています。
チュートリアル:uv2nix による Python 開発環境の構築
このガイドでは、Rust製の高速なパッケージマネージャ uv と Nix を組み合わせ、再現性が高く、かつ既存の開発ツール(LSP等)と互換性のある開発環境を構築します。
1. 準備とプロジェクトの初期化
まだ uv がインストールされていない場合、Nix を使って一時的なシェルに入り、プロジェクトの雛形を作成します。
コマンド:
# 1. uv と python が使えるシェルに入る
nix-shell -p python3 uv
# 2. プロジェクトの初期化(pyproject.toml, .python-version 等が作成される)
uv init --app --package
# 3. ロックファイルの生成
uv lock
2. flake.nix の設定(環境の定義)
uv2nix の核心は、uv.lock を読み込んで Nix のパッケージセットに変換することです。以下の概念を組み合わせて flake.nix を記述します。
-
ワークスペースのロード: プロジェクト全体(
uv.lock)を解析します。 -
オーバーレイの作成:
mkPyprojectOverlayを使い、uv.lockの情報を Nix のビルド指示書(Derivation)に変換します。ここでは「Wheel(バイナリ)」または「sdist(ソース)」の優先度を指定できます。 - Pythonセットの構築: 基本となる Python に、ビルドシステム(setuptools等)と上記のオーバーレイを結合します。
-
Editable モード(開発用): 開発中はソースコードの変更を即座に反映させるため、
mkEditablePyprojectOverlayを使用して、ソースを仮想環境にリンクさせます。
手順 2-1: flake.nix の作成
以下のファイルをflake.nixとして保存します。
uv2nix/templates/hello-world/flake.nix at master · pyproject-nix/uv2nix
3. パッケージの追加と反映(日常のフロー)
uv2nix を導入後のパッケージ管理は、Python 標準のワークフローに従います。flake.nix を編集する必要はありません。
手順 3-1: 依存関係の定義
pyproject.toml を編集し、追加したいライブラリを記述します。
[project]
dependencies = [
"requests",
"numpy",
]
手順 3-2: ロックファイルの更新
ターミナルで以下を実行し、uv.lock を更新します。
uv lock
手順 3-3: 環境の再構築
開発シェルに入り直します。uv2nix が自動的に新しい uv.lock を読み込み、環境を構築します。
nix develop
この環境は標準的な仮想環境(bog-standard virtual environment)として構築されるため、VSCode や Pyright などの LSP ツールがそのまま動作し、補完も効きます。
4. トラブルシューティング:C拡張/バイナリライブラリ
NumPy や PyQt のような C/C++ ライブラリに依存するパッケージを追加した場合、PyPI からダウンロードされた Wheel(バイナリ)が動かないことがあります。
-
自動修正: 通常、
uv2nixはautoPatchelfHookを使用して、Linux 上でバイナリが動くように自動修正を試みます。 -
手動修正(オーバーライド): それでも「ライブラリが見つからない(例:
libstdc++.so.6 missing)」というエラーが出る場合は、flake.nixで不足しているライブラリを手動で追加する必要があります。
修正例 (flake.nix 内のオーバーレイ):
(final: prev: {
numpy = prev.numpy.overrideAttrs (old: {
# 不足しているライブラリ (例: zlib, stdenv.cc.cc.lib) を buildInputs に追加
buildInputs = old.buildInputs ++ [ final.pkgs.zlib ];
});
})
Note: 現在、この不足ライブラリの特定と追加を自動化するツール(auto-rider)が開発中ですが、現時点では手動での対応が必要になることがあります。
この構成により、flake.nix の管理コストを最小限に抑えつつ、Python エコシステムの利便性と Nix の再現性を両立させた開発が可能になります。