Skip to main content

Python uv 教學,最佳專案管理工具(下)

本文介紹 uv 的操作指令,下篇的指令使用率比較低,但仍然是我挑出來比較實用的指令。

建立符合 PEP 723 的腳本

PEP 723 規範 Python 腳本的開頭設定以支援辨識該腳本需要哪些套件才能運行,否則以前需要額外的 requirements.txt 紀錄套件才能執行腳本。PEP 723 格式如下:

# /// script
# # 支援寫註解,要多加上一個井字號
# requires-python = ">=3.8"
# dependencies = [
# "requests<3",
# "beautifulsoup4",
# ]
# ///

這設定了 Python 版本和依賴套件,寫這些很麻煩,不過 uv 可以直接幫你寫:

uv init --script example.py --python 3.8
uv add --script example.py 'requests<3' 'beautifulsoup4'

第一行是建立文件,已經有文件可以跳過第一行,直接使用第二行就會幫你加上設定。

使用 uv tool 取代 pipx

https://docs.astral.sh/uv/guides/tools/

此功能用於取代 pipx,把提供命令行執行的工具安裝在全局環境,例如筆者一開始測試 uv 時也是用 pipx 安裝的。uv tool 特別的地方是沒有安裝也可以執行,會把套件安裝在一個臨時的虛擬環境中。

# 安裝 ruff
uv tool install ruff

# 執行 ruff,uvx 等效於 uv tool run ruff
uvx ruff

# 當套件名稱和命令行名稱不一樣時的指令
# 套件名稱 http,需要透過 httpie xxx 執行
uvx --from httpie http

# 升級
uv tool upgrade

# 指定相依套件版本
uv tool install --with <extra-package> <tool-package>

在 Docker 中使用 uv

uv 對 Docker 的支援也很完善且積極,文檔介紹了各種常見問題,直接查看文檔

發布套件

編譯 requirements.txt

https://docs.astral.sh/uv/concepts/projects/sync/#exporting-the-lockfile

uv export --no-emit-project --locked --no-hashes -o requirements.txt -q

每次都要手動打太麻煩,使用 pre-commit 一勞永逸,自動檢查 lock 檔案是否變動並且匯出。pre-commit 的使用範例可以參考筆者寫的文章

# .pre-commit-config.yaml

repos:
# 使用官方 pre-commit
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.5.14
hooks:
- id: uv-export
args: ["--no-emit-project", "--locked", "--no-hashes", "-o=requirements.txt", "-q"]
# 當 uv.lock 變化時才觸發 (當你升級或增減套件)
files: ^uv\.lock$

# 另一個範例:改用本地 uv,改用 pip compile
- repo: local
hooks:
- id: run-pip-compile
name: Run pip compile
entry: bash -c 'rm -f requirements.txt && uv pip compile pyproject.toml -o requirements.txt --annotation-style line -q'
language: system
files: ^uv\.lock$

uv exportuv pip compile 某種程度上有些相似又不完全相同,前者用於處理 lockfile,後者用於編譯模糊的主要依賴文件 requirements.in,由於還在開發階段就不深入討論。uv 提供各種不同文件的編譯方式,基本上兼容所有想得到的依賴文件。

構建套件

https://docs.astral.sh/uv/reference/cli/#uv-build

uv build --no-sources

發布套件,以 test.pypi 為例

需要指定 build 路徑,預設在 dist 資料夾中。使用時輸入的帳號是 __token__,密碼則是 pypi 提供的 token,注意此指令還在實驗階段隨時可能變動。

uv publish --publish-url https://test.pypi.org/legacy/ dist/*

整合 Github CI

一般來說我們不會每次發布都打 build publish,而是使用自動化流程完成套件發布,下方直接附上 Github Actions 方便抄作業,實測沒問題可以直接複製貼上使用。這個設定不使用已經被建議棄用的 token 方式,而是遵照官方的最佳實踐使用可信任發行者方式,在每次 tag 名稱是 vN.N.N.NvN.N.N 時以及發布 release 時才會啟動,並且建議開啟手動驗證

開啟手動驗證的方式是進入專案首頁後

  1. 點擊上方 Code/Issues 那排最右邊的 Settings
  2. 點擊左側列表的 Environments
  3. 如果成功設定會有一個環境名稱是 publish_pypi
  4. 勾選 Required reviewers 並且設定人員,最多六名。
name: PyPI Publish

on:
release:
types: [created]

push:
tags:
- 'v*.*.*.*'
- 'v*.*.*'

jobs:
publish:
name: Build and Publish to PyPI
environment: publish_pypi
runs-on: ubuntu-latest

permissions:
id-token: write
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: uv.lock

- name: Set up Python
# 不指定子版本會自動使用最新版
uses: actions/setup-python@v5
with:
python-version: '3.x'

- name: Build package
run: uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
# for test.pypi
# with:
# repository-url: https://test.pypi.org/legacy/

Github Dependabot

開發中,尚未支援。

更新進度請查看 dependabot/dependabot-core#10478,uv 建議的替代方案是使用 Renovate,或是用戶自己做的Github Actions Bot

結束

本文介紹了從安裝到平常使用,到 pyproject.toml/.pre-commit-config.yaml 抄作業,到發布套件,以及取代 pipx,甚至於建立 PEP 723 腳本/讀取 env 的全部介紹。