tags : Python, Emacs, mise

概要

macOS + mise 環境で Python 開発環境を構築する手順。 パッケージ管理に uv、エディタに Emacs(eglot + pyright)を使用する。

Python パッケージ管理の全体像

2つの問題

Python のパッケージ管理には2つの別の問題がある。

  1. パッケージのインストール — numpy や torch などのライブラリをどうやって入れるか
  2. プロジェクトごとの環境分離 — 異なるバージョンのライブラリを使い分けたい

Node.js では npm が両方担い node_modules で分離されるが、Python は歴史的にバラバラに発展した。

標準ツール

  • pip — パッケージインストーラ。 npm install 相当
  • venv — 仮想環境を作る標準ツール。プロジェクトごとに独立した環境を作る
python -m venv .venv
source .venv/bin/activate
pip install numpy

問題点: ロックファイルの概念がない、依存解決が遅い、activate が面倒。

モダンなツール

  • poetrypyproject.toml + ロックファイルで依存管理。かつてのデファクト
  • uv — Rust製で高速。pip + venv + プロジェクト管理を1つでこなす。Astral社製(ruff と同じ会社)。今の一番のおすすめ
  • rye — uv の前身。作者が uv チームに合流し実質統合された

Node.js との対比

概念Node.jsPython (標準)Python (uv)
パッケージインストーラnpmpipuv
ロックファイルpackage-lock.jsonなしuv.lock
プロジェクト定義package.jsonpyproject.tomlpyproject.toml
環境分離node_modulesvenvuv が自動管理
スクリプト実行npxuvx

Python プログラムの実行

基本

Python はインタプリタ言語。コンパイル不要でファイルをそのまま実行する。

python hello.py

REPL(対話モード)

python
>>> 1 + 1
2
>>> exit()

uv を使った場合の流れ

uv init my-project
cd my-project
uv add requests        # ライブラリ追加(venv も自動作成)
uv run python main.py  # プロジェクト環境内で実行

uv run が「このプロジェクトの仮想環境の中で実行する」という意味。手動の activate 不要。

モジュールとして実行

python -m http.server 8080
python -m pytest

-m はモジュールとして実行するオプション。

uv セットアップ手順

1. uv のインストール(mise)

mise use -g uv@latest

2. Python のインストール

uv python install 3.12
uv python list          # 確認

ComfyUI は 3.12 系が安定。

3. プロジェクト作成と実行

uv init hello-python
cd hello-python
echo 'print("Hello from uv!")' > main.py
uv run python main.py

初回実行時に .venv が自動作成される。

4. ライブラリの追加

uv add requests

pyproject.toml に依存が追記され、 uv.lock も生成される。

トラブルシューティング

mise の python に古い uv が同梱されている問題

mise で python と uv を別々に管理している場合、python の bin に入っている古い uv が PATH で先に見つかることがある。

which uv  # パスを確認
# /Users/sumisonic/.local/share/mise/installs/python/3.13.2/bin/uv ← これが古い
 
# 解決: python の中の uv を削除
rm /Users/sumisonic/.local/share/mise/installs/python/3.13.2/bin/uv
rm /Users/sumisonic/.local/share/mise/installs/python/3.13.2/bin/uvx
hash -r
uv --version  # mise 管理の最新版が使われる

Emacs 環境設定

2025年のモダンな構成。basedpyright + ruff + apheleia を使用。

採用ツール

コンポーネントツール理由
LSP(型チェック・補完)basedpyrightpyrightより高機能、Node.js不要
Emacs統合eglot標準搭載、安定
フォーマットapheleia + ruff非同期、既存設定と統合
診断flymakeeglotが使用

ツールのインストール

uv tool install basedpyright
uv tool install ruff

eglot + basedpyright 設定

(leaf *python-development
  :config
  ;; basedpyright を eglot に登録
  (with-eval-after-load 'eglot
    (add-to-list 'eglot-server-programs
                 '((python-mode python-ts-mode) . ("basedpyright-langserver" "--stdio"))))
 
  ;; Python モードで eglot 自動起動
  (defun sumisonic/python-setup-eglot ()
    (when (fboundp 'eglot-ensure)
      (eglot-ensure)))
 
  ;; flycheck 無効化(eglot/flymake と競合するため)
  (defun sumisonic/disable-flycheck-for-python ()
    (when (fboundp 'flycheck-mode)
      (flycheck-mode -1)))
 
  (dolist (hook '(python-mode-hook python-ts-mode-hook))
    (add-hook hook #'sumisonic/python-setup-eglot)
    (add-hook hook #'sumisonic/disable-flycheck-for-python)))

apheleia + ruff フォーマット設定

;; apheleia の設定内に追加
(setf (alist-get 'python-mode apheleia-mode-alist) '(ruff-isort ruff))
(setf (alist-get 'python-ts-mode apheleia-mode-alist) '(ruff-isort ruff))

ruff-isort でインポートソート → ruff でフォーマットの順に実行。

org-babel で Python 実行

(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)))

使用例:

  • :results output → print() の出力を取得
  • :results value → 式の評価結果を取得

調査メモ(2025年)

  • ruff-lsp は非推奨ruff server (ネイティブLSP)に移行推奨
  • eglot-python-preset → Emacs 30.2+ が必要、elpacaとの相性問題あり
  • basedpyright → コミュニティ主導でpyrightより積極的に機能追加

更新履歴

  • 2025-02-19: 初版作成
  • 2025-02-19: Emacs環境設定を2025年モダン構成に更新(basedpyright + apheleia + ruff)