uv ïŒpythonããã±ãŒãžãããŒãžã£ãŒïŒã®äœ¿ãæ¹ã詳现ç
Pythonã®ããã±ãŒãžç®¡çã¯ãããŸã§ pipãvenvãpoetry ãªã©ã§è¡ãããŠããŸããããæè¿ uv ãæ³šç®ãéããŠããŸãã
æ¬çš¿ã§ã¯ uv ãã·ã¹ãã éçºã§äœ¿ãããã®è©³çŽ°ãªæ
å ±ãç¹ã«ãpoetryãvenvãpipããã®ç§»è¡æé ã解説ããŸãã
1. uvã®æŠèŠ
1.1 uvãšã¯ïŒ
uv㯠é«éãªåäœãã¯ãã¹ãã©ãããã©ãŒã 察å¿ã®ããã¯ãã¡ã€ã«ãããŒã«ç®¡çãPythonèªäœã®ããŒãžã§ã³ç®¡çãçµ±åãããçŸä»£çãªPythonãããžã§ã¯ãïŒããã±ãŒãžãããŒãžã£ãŒã§ããRustã§èšè¿°ãããŠãããåŸæ¥ã®ããŒã«ïŒpip, poetry, pip-toolsãªã©ïŒã®æ©èœãåäœã§çœ®ãæããããšãã§ããŸãã

1.2 uvã®ã¢ãŒããã¯ãã£
uvã¯Rustã§å®è£ ãããŠãããé«ãããã©ãŒãã³ã¹ãšã¡ã¢ãªå®å šæ§ãèªããŸããRustã®äžŠè¡åŠçèœåãæŽ»çšããäŸåé¢ä¿è§£æ±ºãé«éåããŠããŸãããŸããå¹ççãªãã£ãã·ã¥æ©æ§ãåããŠãããããŠã³ããŒãããããã±ãŒãžããã«ããããwheelãã¡ã€ã«ããœãŒã¹ã³ãŒããªã©ããã£ãã·ã¥ããããšã§ãåå©çšæ§ãé«ããåŠçæéãççž®ããŸãããã®ãã£ãã·ã¥ã¯ã¹ã¬ããã»ãŒãã§ãããè€æ°ã®ã³ãã³ããåæå®è¡ããŠãå®å šã«åäœããŸãã
1.3 uvã®ã€ã³ã¹ããŒã«ãšã»ããã¢ãã
uvã®ã€ã³ã¹ããŒã«ã¯ãå ¬åŒã®ã¹ã¿ã³ãã¢ãã³ã€ã³ã¹ããŒã©ãŒãå©çšããã®ãæãç°¡åã§ããmacOSãšLinuxã§ã¯curlã³ãã³ããWindowsã§ã¯PowerShellã³ãã³ããå®è¡ããããšã§ãææ°çã®uvãããŠã³ããŒãããŠã€ã³ã¹ããŒã«ã§ããŸãã
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
ãŸããpipãHomebrewãCargoãšãã£ãããã±ãŒãžãããŒãžã£ãŒãããã€ã³ã¹ããŒã«å¯èœã§ãã
# pip
pip install uv
# Homebrew
brew install uv
# Cargo
cargo install --git https://github.com/astral-sh/uv uv
ã€ã³ã¹ããŒã«åŸãuv generate-shell-completionã³ãã³ããå®è¡ããããšã§ãã·ã§ã«ã«èªåè£å®æ©èœã远å ã§ããŸãã
uvã®ã¢ããã°ã¬ãŒãã¯ãuv self updateã³ãã³ãã§å®è¡ã§ããŸããã¢ã³ã€ã³ã¹ããŒã«ã¯ãuv self uninstallããŸãã¯ã€ã³ã¹ããŒã«ãã£ã¬ã¯ããªãããã€ããªãåé€ããã ãã§å®äºããŸãã
2. uvã®åºæ¬çãªäœ¿ãæ¹
2.1 PythonããŒãžã§ã³ã®ç®¡ç
uvã¯ãè€æ°ã®PythonããŒãžã§ã³ã管çããããšãã§ããŸããuv python installã³ãã³ãã§ãä»»æã®ããŒãžã§ã³ã®Pythonãã€ã³ã¹ããŒã«ã§ããŸãã
uv python install 3.11 3.12 3.13
uv python listã³ãã³ãã§ãã€ã³ã¹ããŒã«å¯èœãªããŒãžã§ã³ãã€ã³ã¹ããŒã«æžã¿ã®ããŒãžã§ã³ã確èªã§ããŸãã
uv python list
ãããžã§ã¯ãããšã«äœ¿çšããPythonããŒãžã§ã³ãæå®ããã«ã¯ã.python-versionãã¡ã€ã«ã«ããŒãžã§ã³ïŒäŸ: 3.12ïŒãèšè¿°ããããpyproject.toml ã«èšè¿°ããŸãã
uvã¯ãã³ãã³ãå®è¡æã«å¿ èŠãªPythonããŒãžã§ã³ãèŠã€ãããªãå Žåãèªåçã«ããŠã³ããŒãããŠäœ¿çšããŸãã
2.2 ã¹ã¯ãªããã®å®è¡
uvã¯ãã¹ã¿ã³ãã¢ãã³ã¹ã¯ãªããã®å®è¡ããµããŒãããŠããŸããuv runã³ãã³ãã§ããããžã§ã¯ãç°å¢ãäžæçãªç°å¢ã§ã¹ã¯ãªãããå®è¡ã§ããŸãã
uv run example.py
ã¹ã¯ãªããã«å¿
èŠãªäŸåé¢ä¿ã¯ã--withãªãã·ã§ã³ã§æå®ããããšã§ãäžæçãªä»®æ³ç°å¢ãäœæããŠå®è¡ãããŸãã
uv run --with requests example.py
ãŸããã¹ã¯ãªããã®å é ã«ã€ã³ã©ã€ã³ã¡ã¿ããŒã¿ïŒPEP 723ïŒãèšè¿°ããããšã§ãäŸåé¢ä¿ãèªå·±å®çµçã«å®£èšã§ããŸãã
# /// script
# dependencies = ["requests"]
# ///
import requests
# ...
2.3 ããŒã«ã®å®è¡ãšã€ã³ã¹ããŒã«
uvã¯ãPythonããã±ãŒãžãæäŸããã³ãã³ãã©ã€ã³ããŒã«ã®å®è¡ãšã€ã³ã¹ããŒã«ããµããŒãããŠããŸããuvxã³ãã³ã (ãŸãã¯uv tool run) ã§ãã€ã³ã¹ããŒã«ããã«ããŒã«ãäžæçã«å®è¡ã§ããŸãã
uvx ruff check
é »ç¹ã«äœ¿çšããããŒã«ãæ°žç¶çã«ã€ã³ã¹ããŒã«ããã«ã¯ãuv tool installã³ãã³ãã䜿çšããŸããããã«ãããããŒã«ããšã«éé¢ãããç°å¢ãäœãããŸãã
uv tool install ruff
ããã±ãŒãžåãšã³ãã³ãåãç°ãªãå Žåã¯ã--fromãªãã·ã§ã³ã䜿çšããŸãã
uvx --from httpie http
3. uvã«ãããããžã§ã¯ã管ç
3.1 ãããžã§ã¯ãã®äœæãšåæå
uvã¯ãæšæºä»æ§ïŒPEP 621ïŒã«åºã¥ãã pyproject.toml ã«ãããããžã§ã¯ã管çããµããŒãããŠããŸããuv initã³ãã³ãã§ãæ°ãããããžã§ã¯ããäœæã§ããŸãã
uv init my-project
ããã©ã«ãã§ã¯ã¢ããªã±ãŒã·ã§ã³ãããžã§ã¯ãïŒ--appçžåœïŒãäœæãããŸããã--libãªãã·ã§ã³ã§ã©ã€ãã©ãªãããžã§ã¯ããäœæã§ããŸãã
# ã¢ããªã±ãŒã·ã§ã³ãããžã§ã¯ãïŒããã¯ãã¡ã€ã«ãçæããç°å¢ã管çããïŒ
uv init --app my-app
# ã©ã€ãã©ãªãããžã§ã¯ãïŒé
åžçšããã±ãŒãžãäœæããïŒ
uv init --lib my-lib
uv initã§ã¯ãhatchlingãflit-coreãsetuptoolsãmaturin ãšãã£ããã«ãããã¯ãšã³ããéžæã§ããŸãã--build-backendãªãã·ã§ã³ã§æå®å¯èœã§ãã
uv init --lib --build-backend maturin my-lib
3.2 äŸåé¢ä¿ã®ç®¡ç
uv addã³ãã³ãã§ãpyproject.tomlã® project.dependencies ã«äŸåé¢ä¿ã远å ããåæã«ä»®æ³ç°å¢ãžã€ã³ã¹ããŒã«ããŸãã
uv add requests
--devãªãã·ã§ã³ã§ãéçºçšã®äŸåé¢ä¿ïŒdependency-groups ãŸã㯠project.optional-dependenciesïŒã远å ã§ããŸãã
uv add --dev pytest
uv removeã³ãã³ãã§ãäŸåé¢ä¿ãåé€ã§ããŸãã
uv remove requests
3.3 ç°å¢ã®ç®¡ç
uvã¯ããããžã§ã¯ãã«ãŒãã« .venv ãšããä»®æ³ç°å¢ãèªåçã«äœæã»ç®¡çããŸããuv syncã³ãã³ãã§ãuv.lock ãã¡ã€ã«ã®å
容ã«åºã¥ããŠä»®æ³ç°å¢ãææ°ã®ç¶æ
ã«åæããŸãã
uv sync
--frozenãªãã·ã§ã³ãã€ãããšãããã¯ãã¡ã€ã«ã®æŽæ°ãè¡ããã«åæãããããCI/CDç°å¢ã§ã®å©çšã«é©ããŠããŸãã
--no-editableãªãã·ã§ã³ã§ãèªèº«ã®ãããžã§ã¯ããç·šéäžå¯ã¢ãŒãã§ã€ã³ã¹ããŒã«ã§ããŸããããã¯ãDockerã³ã³ããã®æ§ç¯ãªã©ããããã€æã«äŸ¿å©ã§ãã
3.4 ããã¯ãã¡ã€ã«ã®ç®¡ç
uvã¯ãuv.lockãšããã¯ãã¹ãã©ãããã©ãŒã ã®ããã¯ãã¡ã€ã«ãçæããŸããããã¯Git管ç察象ãšãã¹ããã¡ã€ã«ã§ãã
uv lockã³ãã³ãã§ãä»®æ³ç°å¢ã倿Žããã«ããã¯ãã¡ã€ã«ã®ã¿ãæŽæ°ã§ããŸãã
uv lock --upgrade
3.5 ã¯ãŒã¯ã¹ããŒã¹ã®æŽ»çš
uvã¯ãCargoã¹ã¿ã€ã«ã®ã¯ãŒã¯ã¹ããŒã¹ããµããŒãããŠããŸããããã«ãããåäžã®ãªããžããªïŒMonorepoïŒã§è€æ°ã®ããã±ãŒãžããŸãšããŠç®¡çã§ããŸãã
pyproject.tomlã«tool.uv.workspaceããŒãã«ã远å ããããšã§ãã¯ãŒã¯ã¹ããŒã¹ãäœæã§ããŸãã
[tool.uv.workspace]
members = ["packages/*"]
ã¯ãŒã¯ã¹ããŒã¹ã¡ã³ããŒéã§ã¯ãtool.uv.sourcesãå©çšããŠçžäºäŸåãå®çŸ©ã§ããuv sync äžçºã§ã¯ãŒã¯ã¹ããŒã¹å
šäœã®ç°å¢ãæ§ç¯ã§ããŸãã
4. uvã®é«åºŠãªæ©èœ
4.1 äŸåé¢ä¿ã®è§£æ±º
uvã¯é«åºŠãªäŸåé¢ä¿è§£æ±ºã¢ã«ãŽãªãºã ãåããŠããã以äžã®èŠçŽ ãèæ ®ããŠãã¹ãŠã®äŸåé¢ä¿ãæºããæé©ãªããã±ãŒãžã®çµã¿åãããæ¢çŽ¢ããŸãã
- ããŒãžã§ã³å¶çŽ: åããã±ãŒãžã«æå®ãããããŒãžã§ã³ç¯å²
- ãã©ãããã©ãŒã ããŒã«ãŒ: OSãã¢ãŒããã¯ãã£ãPythonããŒãžã§ã³ãªã©ã®æ¡ä»¶
- äŸåé¢ä¿ã®ç«¶å: ç°ãªãããã±ãŒãžãåãäŸåé¢ä¿ã®ç°ãªãããŒãžã§ã³ãèŠæ±ããå Žå
uvã¯ããŠãããŒãµã«è§£æ±ºïŒããã©ã«ãïŒãè¡ããLinux, macOS, Windowsãªã©å
šãŠã®ãã©ãããã©ãŒã ã§åäœããåäžã® uv.lock ãçæããŸããããã«ãããããŒã ã¡ã³ããŒã®OSãç°ãªã£ãŠãåãäŸåé¢ä¿ã»ãããä¿èšŒãããŸãã
4.2 ãã£ãã·ã¥ã®ç®¡ç
uvã¯ã匷åãªã°ããŒãã«ãã£ãã·ã¥æ©æ§ãåããŠããŸãã
uv cache cleanã³ãã³ãã§ããã£ãã·ã¥ããã¹ãŠåé€ã§ããŸããuv cache pruneã³ãã³ãã§ãæªäœ¿çšã®ãã£ãã·ã¥ãšã³ããªãåé€ã§ããŸããCIç°å¢ãªã©ã§ãã£ãã·ã¥ãã£ã¬ã¯ããªãæå®ãããå Žå㯠UV_CACHE_DIR ç°å¢å€æ°ãå©çšã§ããŸãã
4.3 ãã«ãã®åé¢
uvã¯ãPEP 517ãšPEP 660ã«æºæ ãããã«ãã®åé¢ããµããŒãããŠããŸããåããã±ãŒãžãéé¢ãããç°å¢ã§ãã«ãããããšã§ãäŸåé¢ä¿ã®ç«¶åãé²ããŸãã
4.4 ãããªãã·ã¥
uvã¯ãuv buildã³ãã³ãã§Pythonããã±ãŒãžããœãŒã¹ãã£ã¹ããªãã¥ãŒã·ã§ã³ãšãã€ããªãã£ã¹ããªãã¥ãŒã·ã§ã³ã«ãã«ãããuv publishã³ãã³ãã§PyPIãªã©ã®ã¬ãžã¹ããªã«ã¢ããããŒãããããšãã§ããŸããèªèšŒã«ã¯Trusted PublishingãAPIããŒã¯ã³ãå©çšå¯èœã§ãã
5. uvãšä»ããŒã«ãšã®é£æº
5.1 Dockerãšã®é£æº
uvã¯ãDockerã§ã®å©çšã«æé©åãããŠããŸããå ¬åŒDockerã€ã¡ãŒãžãå©çšããããšã§ãç°¡åã«ã»ããã¢ããã§ããŸãã
FROM python:3.12-slim
# å
¬åŒã€ã¡ãŒãžããuvãã³ããŒ
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# äŸåé¢ä¿ãã¡ã€ã«ã®ã³ããŒ
COPY pyproject.toml uv.lock ./
# äŸåé¢ä¿ã®ã€ã³ã¹ããŒã«ïŒã·ã¹ãã ç°å¢ã«çŽæ¥ã€ã³ã¹ããŒã«ïŒ
RUN uv sync --frozen --no-cache
COPY . .
Dockerã³ã³ããå
ã§ã¯ä»®æ³ç°å¢ãäœãããã·ã¹ãã Pythonã«ã€ã³ã¹ããŒã«ããã®ãäžè¬çã§ãããã®å Žåãuv sync ã¯ããã©ã«ãã§ .venv ãäœãããšãããããç°å¢å€æ° UV_PROJECT_ENVIRONMENT=/usr/local ãèšå®ããããuv pip install --system ã³ãã³ããªã©ã䜵çšããææ³ããããŸãããã ããææ°ã®ãã¹ããã©ã¯ãã£ã¹ã§ã¯ãRUN uv sync --frozen --no-install-project ã§äŸåé¢ä¿ã®ã¿ãã€ã³ã¹ããŒã«ããææ³ãæšå¥šãããŸãã
5.2 GitHub Actionsãšã®é£æº
GitHub Actionsã§ã¯ãå
¬åŒã®astral-sh/setup-uvã¢ã¯ã·ã§ã³ãå©çšããŸãã
steps:
- uses: actions/checkout@v7
- name: Install uv
uses: astral-sh/setup-uv@v10
with:
enable-cache: true
- name: Install dependencies
run: uv sync --frozen
- name: Run tests
run: uv run pytest
enable-cache: true ãèšå®ããã ãã§ããã£ãã·ã¥ã®ä¿åã»åŸ©å
ãèªåçã«è¡ãããã¯ãŒã¯ãããŒãé«éåããŸãã
5.3 GitLab CI/CDãšã®é£æº
GitLab CI/CDã§ããå ¬åŒDockerã€ã¡ãŒãžãå©çšã§ããŸãã
variables:
UV_VERSION: 0.5
PYTHON_VERSION: 3.12
uv-job:
image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-bookworm-slim
script:
- uv sync --frozen
- uv run pytest
5.4 Jupyterãšã®é£æº
ãããžã§ã¯ãå
ã§Jupyterã䜿çšããã«ã¯ãuv runã³ãã³ãçµç±ã§èµ·åããã®ã確å®ã§ãã
# JupyterLabãäžæçã«å®è¡ããå Žå
uvx --with jupyter jupyter lab
# ãããžã§ã¯ãã®äŸåé¢ä¿ãšããŠè¿œå æžã¿ã®å Žå
uv run jupyter lab
æ¢åã®Jupyterç°å¢ããuvã®ä»®æ³ç°å¢ãã«ãŒãã«ãšããŠå©çšãããå Žåã¯ãuv add --dev ipykernel ããäžã§ã«ãŒãã«ãç»é²ããŸãã
uv run python -m ipykernel install --user --name=my-project
5.5 pre-commitãšã®é£æº
uvã¯ãpre-commitããã¯ãæäŸããŠããŸããäŸãã°ãuv.lock ã pyproject.toml ãšåæãããŠãããããã§ãã¯ããããrequirements.txt ãèªåçæãããã§ããŸãã
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.12.5
hooks:
# uv.lockãææ°ããã§ãã¯ãã
- id: uv-lock
# (ãªãã·ã§ã³) requirements.txtãèªåãšã¯ã¹ããŒãããå Žå
- id: uv-export
args: ["--format", "requirements-txt", "--output-file", "requirements.txt"]
6. poetry, venv, pipããã®ç§»è¡
çŸåšä»ã®ããŒã«ã䜿çšããŠããããŒã ããuvã®ãããžã§ã¯ãç®¡çæ©èœïŒuv sync / uv runïŒãžç§»è¡ããæé ã¯ä»¥äžã®éãã§ãã
6.1 poetryããã®ç§»è¡
Poetryã¯ç¬èªã® [tool.poetry] èšå®ã䜿çšããŸãããuvã¯æšæºã®PEP 621 [project] èšå®ã䜿çšããŸãã
-
pyproject.tomlã®æžãæã: Poetry圢åŒã®èšè¿°ããæšæºçãª
[project]ããŒãã«ã«æžãæããŸããäŸåé¢ä¿ã¯tool.poetry.dependenciesããproject.dependenciesã«ç§»åããŸãã- â» æåã§ã®æžãæããåºæ¬ã§ãããäžåºŠ
requirements.txtãåãåºããŠããåãèŸŒãæ¹æ³ã簡䟿ã§ãã
- â» æåã§ã®æžãæããåºæ¬ã§ãããäžåºŠ
-
äŸåé¢ä¿ã®åã蟌ã¿:
# Poetryã§äŸåé¢ä¿ãåºå poetry export -f requirements.txt --output requirements.txt --without-hashes # uvãããžã§ã¯ãã®åæå uv init # requirements.txtããäŸåé¢ä¿ãäžæ¬è¿œå uv add -r requirements.txt # éçºçšäŸåé¢ä¿ãåæ§ã« poetry export --only dev -f requirements.txt --output dev-requirements.txt uv add --dev -r dev-requirements.txt -
ã¯ãªãŒã³ã¢ãã: äžèŠã«ãªã£ã
poetry.lockãrequirements.txtãåé€ããçæãããuv.lockãã³ãããããŸãã
6.2 venv, pipããã®ç§»è¡
-
äŸåé¢ä¿ã®ãšã¯ã¹ããŒã: æ¢åç°å¢ããäŸåãªã¹ããåºåããŸããïŒããæ¢ã«ææžãã®
pip freeze > requirements.txtrequirements.txtãããå Žåã¯ããã䜿çšããŸãïŒ -
uvãããžã§ã¯ãã®äœæ:
uv init -
äŸåé¢ä¿ã®ç§»è¡:ããã«ããã
uv add -r requirements.txtrequirements.txtã®å 容ãpyproject.tomlã«è»¢èšãããuv.lockãçæãããŸããä»åŸã¯requirements.txtãçŽæ¥ç·šéããã®ã§ã¯ãªããuv add/uv removeã§ç®¡çããŸãã
7. uvã®ã¡ãªãããšãã¡ãªãã
ã¡ãªããïŒ
- å§åçãªããã©ãŒãã³ã¹: Rustã«ããå®è£ ã«ããäŸåé¢ä¿è§£æ±ºãšã€ã³ã¹ããŒã«ãéåžžã«é«éã§ãã
- All-in-One: Pythonã€ã³ã¹ããŒã«ãããã±ãŒãžç®¡çããããžã§ã¯ã管çãããŒã«å®è¡ããã1ã€ã§å®çµããŸãã
-
æšæºæºæ : ç¬èªã®ã¡ã¿ããŒã¿åœ¢åŒã§ã¯ãªããæšæºã®PEP 621 (
pyproject.toml) ãæ¡çšããŠããŸãã - ã¯ãã¹ãã©ãããã©ãŒã : Windows, Mac, Linuxã§äžè²«ããããã¯ãã¡ã€ã«ã䜿çšã§ããŸãã
ãã¡ãªããïŒ
- ãšã³ã·ã¹ãã ã®æç床: æ¥éã«éçºãé²ãã§ãããããç Žå£çãªå€æŽãå ¥ãããšãçšã«ãããŸãããv0.5以éã¯ããªãå®å®ããŠããŸãã
- äžéšã®ãã«ãããŒã«ãšã®çžæ§: éåžžã«ç¹æ®ãªãã«ãèšå®ãæã€å€ãããã±ãŒãžã®å Žåãèšå®ãå¿ èŠãªããšããããŸãã
åç §
- uvå ¬åŒããã¥ã¡ã³ã
- uv (github)
- ãã«ããšäŸåé¢ä¿ïŒäŸåã°ã©ãã»å¢åãã«ãã®æ£ããã»çã®è§£æ±ºïŒRikaiïŒ
çè ã¯å€¢çŸæç ååäŒç€Ÿãéå¶ããŠããŸããæ°åŠã»ç©çåŠã»æ å ±ç§åŠãè¡éãåããŠè§£èª¬ããæç§æžãµã€ããRikaiããå ¬éããŠããã®ã§ããããã°ã芧ãã ããã
Discussion