npm感覚でPython環境を構築!非PythonエンジニアがuvでPythonプロジェクト(Talk to the City)を動かす
uv を使った Python のパッケージ依存関係の解決方法を解説していきます。
業務やプライベートで扱う言語は Node.js がメインで、普段は npm や pnpm を使ってライブラリの依存関係を解決しています。
そんな私がある機会でTalk to the Cityを検証して欲しいと頼まれました。
Talk to the City は 2024 年の東京都知事選挙で安野たかひろ氏のチームが使ったことで注目された Python プロジェクトです。
Python の開発環境を作って README 通りに動作させてやれば良いかと進めていったところで絶望しました。
DevContainer を用いてクリーンな Python の実行環境を用意して試したのですが、2025 年 3 月 19 日現在、デモ通り動かしてもエラーが発生します。

ImportError: cannot import name 'cached_download' from 'huggingface_hub' (/workspaces/talk-to-the-city-reports/scatter/venv/lib/python3.10/site-packages/huggingface_hub/__init__.py)
エラーログの最終行にこの記述があり、どうやらbertopic==0.15.0かsentence-transformers==2.2.2のどちらかが、requirements.txtに記載の無いhuggingface_hubパッケージの新しめのバージョンを参照し、既に削除されたメソッドを使用しているようです。
上記の再現手順
git clone https://github.com/AIObjectives/talk-to-the-city-reports.git
VS Code で/scatterをワークスペースとして開き、コマンドパレットから開発コンテナー: コンテナーでリビルドして再度開く Dev Containers: Rebuild and Reopen in Containerを実行して、Python3.11-bullseye のテンプレートを選択して DevContainer を作成
https://github.com/AIObjectives/talk-to-the-city-reports/blob/main/scatter/pipeline/inputs/example-polis.csv から csv ファイルを手動でダウンロードして/scatter/pipeline/inputsに入れる。(Git LFS を使うのがめんどくさかったため)
DevContainer でターミナルを開き以下を実行
# 環境の用意
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python -c "import nltk; nltk.download('stopwords')"
cd pipeline
OPENAI_API_KEY='OPEN_AIのAPIキー' && python main.py configs/example-polis.json
依存関係の解決(requirements.txt)は、現時点(2025 年 3 月 19 日)から見ると 2 年前がラストコミットです。LLM 分野のパッケージは更新が非常に早いでしょうから、動かなくなるのも仕方ありません。
uv を使って Python の実行環境をまるっと設定する
ここまでやってきて Python プロジェクトのめんどくさい点は、requirements.txtを使ったパッケージ解決の部分と、その元となる実行環境を整える部分にあると思います。
また、最初の例では、DevContainer を用意しましたが、これぐらいの動作検証だったら大げさに仮想環境を立てることなく使用しているホストマシン(自分の場合は Mac)から直接 Python を実行したいです。
したいですが...
Python ではパッケージ管理を行うpipが依存をローカルにインストールする機能を持っていないため狙った環境を揃えるのも一苦労です。
デフォルトで Python がvenvを使用し、pip をローカルに扱える仮想環境を用意してくれています。
しかし、それだけでは Python のバージョンを切り替えることはできません。
また、いちいちプログラムを実行するために仮想環境に入らなければいけないのは普段は Node.js を使ってローカルから直に開発している身としては大変に感じます。
そこで、uv という最近、市民権を得ている Python のパッケージマネージャーがオススメです。
現在話題の AI エージェントツール、OpenManus のインストールでも uv が推奨されているほどには市民権を得ています。
uv を使えば、Python バイナリも uv がマシンに合わせて適切に落としてきてくれますし、pyproject.tomlでバージョンを指定して切り替えることもできます。
また、npm の出力するpackage-lock.jsonのようにuv.lockという依存関係を全て明記したファイルも生成してくれるので、今回のような依存関係で時間が経って実行できないという体験も少なくなるでしょう。
uv は、Python 本体の仮想環境(venv)やパッケージ管理ツール(pip)を内部で呼び出し、ラッパー的に操作する仕組みになっています。(たぶん)
requirements.txt から uv に移行する
Talk to the City のように uv が使われておらず既にrequirements.txtのみでパッケージ管理がされている Python プロジェクトでしたら、新しく uv プロジェクトとしてセットアップします。
astral-sh/uv の READMEを参考に uvコマンドを使えるようにした後に
uv init
を実行するとpyproject.tomlが生成されます。$ uv initでは、サンプル用のmain.pyが一緒に作られますが、不要であれば削除して構いません。
今回の場合は、Python3.10 の最新バージョンを使って欲しいので、pyproject.tomlを開いてrequires-pythonのところを==3.10.*のように指定します。
そして、以下のコマンドを使えば、requirements.txtから読み取る形でpyproject.tomlのdependenciesにパッケージを転記してくれます。
uv add -r requirements.txt
[project]
name = "scatter"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = "==3.10.*"
dependencies = [
"bertopic==0.15.0",
"hdbscan==0.8.33",
"langchain==0.0.308",
"numpy==1.25.2",
"openai==0.28.1",
"pandas==2.1.1",
"path==16.7.1",
"scikit-learn==1.3.1",
"sentence-transformers==2.2.2",
"spacy==3.7.0",
"tiktoken==0.5.1",
"tqdm==4.66.1",
"umap-learn==0.5.4",
]
$ uv syncというコマンドを実行するとホストマシンにpyconfig.tomlが使う依存をダウンロードしてきてくれます。
uv sync
これで、DevContainer で用意した環境と同じようにホストマシンでも実行できるようになりました。uv run main.pyのコマンドで uv 経由で venv の環境の中でプログラムを実行してくれます。
cd pipeline
OPENAI_API_KEY="OPEN_AIのAPIキー" uv run main.py configs/example-polis.json
uv で新しく依存関係を解決する
uv に移行はできましたが、Talk to the City の場合は参照元にしているrequirements.txtに不備があるので DevContainer の例と同様に動きませんでした。
そこで動くかどうかは運任せになりますが、パッケージをアップデートすることにしました。
uv を使ってpyproject.tomlのdependenciesにソースコードから参照されているパッケージのみを追加して、残りの依存解決はuv.lockに任せます。
まずは、requirements.txtを見てプロジェクトが直接 Import しているパッケージを特定します。

ここの手順は AI にワンライナースクリプトにしてもらいました
grep -F -x -f <(find . -name '*.py' -exec grep -rhoE "^(from|import)\s+([a-zA-Z0-9_]+)" {} \; | awk '{print $2}' | cut -d'.' -f1 | sort -u) <(cut -d= -f1 requirements.txt | sed 's/-/_/g' | sort -u)
以下のパッケージがプロジェクトの.pyファイルから直接 Import されていそうでした。
bertopic
hdbscan
langchain
numpy
openai
pandas
path
sentence_transformers
spacy
tiktoken
tqdm
pyproject.tomlのdependenciesとuv.lockを一旦消して、これらをuv addでこれらの依存を解決しながらインストールしてもらいます。
uv add -n bertopic hdbscan langchain numpy openai pandas path sentence_transformers spacy tiktoken tqdm
ここでまたエラーが出てしまいました。

RuntimeError: Cannot install on Python version 3.10.16; only versions >=3.6,<3.10 are supported.
とあるように Python3.10 だと依存するパッケージのビルドに失敗してしまうので、Python3.9 でトライしてみます。pyproject.tomlをrequires-python = "==3.9.*"に変更すれば良いだけなので簡単です。
[project]
name = "scatter"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = "==3.9.*"
dependencies = []
変更後は$ uv syncを実行してマシンにバイナリをダウンロードします。
その後、Python3.9 で$ uv run main.py configs/example-polis.jsonを実行したらいくつかのエラーが出ました。
To install langchain-community run
pip install -U langchain-community.
とエラーに出てきたので従います。
uv pip install -U langchain-community
次に
ModuleNotFoundError: No module named 'nltk'
と出てきて、Talk to the City の求めるセットアップを DevContainer に変えてから行ってなかったので行います。
uv pip install nltk
uv run python -c "import nltk; nltk.download('stopwords')"
このようにuvコマンド越しにvenvの仮想環境でpipコマンドが使えるのは楽で良いです。
最終的に、$ uv run main.py configs/example-polis.jsonの処理を最後まで成功させることができました。
まとめ
以上になります。
もし、「普段は Python をあまり触らないけれど、ちょっとした検証で Python プロジェクトを動かす必要がある」という方がいたら、ぜひ uv を使って環境構築をしてみてください。
(この記事のテキストは、ほぼ 100% 人間の手によって書かれています。)
Discussion
uvはRustで実装されていてPythonを直接は利用しません。uvから使えるvenvやpipコマンドはPython版と同様のインターフェースをしているだけで実際にはRustで実装されています。以下の両者は異なります。
また、理解したうえでやってらっしゃるかもしれませんが、uv add/syncとuv pipは混ぜて使用せずに基本的にはuv add/syncのみを使用するのがパッケージ管理としては正しく、npmやcargoなどと同じ挙動になります。uv pipはあくまでpipとの互換性のためだけにある機能です。
こちらの補足ありがとうございます!リンクする形で本文の方にも引用しておきますね。
こちらも補足ありがとうございます!
uvの仕組みを把握してプロジェクトを全てuv add/uv syncに移行せずとも、一時的に解決するだけならハック的に
uv pipでpipを使った情報に沿って行えるのもPythonianでない方にuvをオススメしたくなった動機です😊。(pipと別物としてuvを学習するのではなくpipの延長線上という理解の上で操作できるインターフェースが魅力的ですね。)