uv 怎麼升級相依套件:單一套件更新、版本限制、uv.lock 與回復教學

uv sync 為什麼不升級套件?透過範例說明 uv lock --upgrade-package、uv add 版本限制、--locked 與 --frozen 的差異,以及更新後的驗證與回復方法。

在 uv 專案中升級一個相依套件,先用 uv lock --upgrade-package 包名 更新鎖定檔,再用 uv sync --locked 安裝並驗證。若專案宣告的版本範圍不允許目標版本,需要先調整 pyproject.toml 中的限制。

最常見的誤會是把「同步環境」當成「尋找最新版」:執行 uv sync 後套件沒有變化,往往是 uv 正在遵守現有的鎖定檔。

本文適用於已有 pyproject.toml 的 Python 專案,指令以 PowerShell 為例,核心 uv 指令也適用於 Linux 和 macOS。 範例使用 requests 和 pytest,方便在獨立練習目錄中驗證,不需要連接模型 API。 文件核對日期為 2026 年 10 月 11 日;本文沒有測試任何特定 AI 專案升級後的相容性。

先分清楚你要更新哪一層

同一句「更新 uv」,可能對應三種不同的對象。 先確定對象,可以避免升級了工具,卻發現專案相依套件完全沒變。

目標 常用操作 主要影響
uv 程式本身 透過原安裝管道升級 uv 套件管理工具版本
專案中的一個相依套件 uv lock --upgrade-package requests 鎖定檔中的相依解析結果
專案允許的相依版本範圍 uv add "requests>=2.32,<3" 專案宣告、鎖定檔和環境
專案全部相依套件 uv lock --upgrade 所有可升級的鎖定相依套件
透過 uv tool 安裝的工具 uv tool upgrade 工具名 工具自己的隔離環境

不要用 uv tool upgrade 更新專案裡的 requests。 也不要只升級 uv 程式,就認為 .venv 中的套件會自動更新。 工具安裝和專案相依套件是兩個維護範圍,詳見 uv 工具指南。

pyproject.toml、uv.lock、.venv 分別管理什麼

一次相依變更可以理解為三個連續問題:專案允許什麼版本、解析決定使用什麼版本、目前電腦實際安裝了什麼版本。

檔案或目錄 職責 是否提交到 Git
pyproject.toml 宣告直接相依套件及允許範圍 是
uv.lock 儲存精確解析結果 是
.python-version 記錄專案選擇的 Python 版本 通常是
.venv 目前電腦安裝出的環境 否

例如,專案宣告如下:

1
2
3
4
5
6
7
[project]
name = "dependency-demo"
version = "0.1.0"
requires-python = ">=3.12,<3.13"
dependencies = [
    "requests>=2.31,<3",
]

這段設定允許 requests 的一段版本範圍。 它沒有要求每次執行都安裝這段範圍內的最新版本。

如果 uv.lock 已鎖定一個符合條件的版本,一般同步通常會繼續使用它。 這種行為能減少「昨天可以執行,今天重新安裝就壞了」的意外。 相關機制見 uv 鎖定與同步文件。

用獨立目錄練習單一套件升級

先確認工具存在:

1
2
uv --version
git --version

選擇一個不存在的目錄名稱,避免把練習檔案寫進正在維護的儲存庫。 下面使用指令稿型專案,不需要設定 Python 套件的建置後端。

1
2
3
4
5
6
uv init --bare --python 3.12 uv-update-demo
Set-Location uv-update-demo
uv python pin 3.12
uv add "requests>=2.31,<3"
uv add --dev pytest
uv sync --locked

如果本機沒有所需 Python,uv 可能需要下載直譯器。 在受限網路中應先解決下載或直譯器尋找問題,再判斷相依套件是否衝突。 Python 版本選擇規則見 官方直譯器文件。

建立 main.py:

1
2
3
4
5
6
7
from importlib.metadata import version
import requests

request = requests.Request("GET", "https://example.com/").prepare()
print("requests:", version("requests"))
print("method:", request.method)
print("url:", request.url)

這段程式碼只建立請求,不發送網路請求。 它能檢查套件是否可以匯入,並顯示目前環境實際安裝的版本。

1
2
uv run --locked python main.py
uv tree --locked

接著建立練習基準:

1
2
3
4
git init
git status --short
git add pyproject.toml uv.lock .python-version main.py
git commit -m "Record dependency baseline"

提交前確認 .venv 沒有進入暫存區。 若尚未設定 Git 身分,可以先保留檔案副本;後面的 Git 回復指令需要已存在的提交。

升級一個套件,並檢查它帶來的變化

在剛才的專案目錄執行:

1
2
3
4
uv lock --upgrade-package requests
git diff -- uv.lock
uv sync --locked
uv run --locked python main.py

這裡將解析和安裝分開,是為了先看清鎖定檔變化,再修改工作環境。 如果比較習慣一次完成,也可以使用 uv sync --upgrade-package requests。

「單一套件升級」表示以這個套件為更新目標,並不保證鎖定檔只改一個項目。 目標套件的新版本可能需要不同的間接相依套件,解析器仍須找出滿足整個專案的組合。

檢查差異時重點看這些問題:

  • requests 本身是否變化。
  • 是否新增或移除了間接相依套件。
  • 下載來源是否仍符合專案預期。
  • 是否有其他限制使目標套件停留在原版本。

剛建立的練習專案通常已選中目前可用的版本。 因此再次升級沒有差異也屬於正常結果,不代表指令失敗。

查看安裝結果時,使用專案直譯器:

1
2
uv run --locked python -c "import sys; print(sys.executable)"
uv run --locked python -c "from importlib.metadata import version; print(version('requests'))"

第一條輸出應指向專案環境。 若編輯器顯示的版本不同,先檢查編輯器選中的 Python 路徑。

為什麼升級指令仍停在舊版本

假設專案寫的是:

1
2
3
dependencies = [
    "requests==2.31.0",
]

精確限制只允許這個版本。 --upgrade-package 不會替你突破專案宣告。

若已完成相容性評估,決定允許後續版本,可以明確修改範圍:

1
2
3
uv add "requests>=2.32,<3"
git diff -- pyproject.toml uv.lock
uv run --locked python main.py

uv add 預設會更新宣告、鎖定檔和環境,因此這一步已經可能安裝新套件。 請在獨立分支中執行,避免把它當成唯讀查詢。

如果只打算驗證一個特定版本,應明確宣告精確版本,再進行測試。 不要為了讓解析通過而刪除全部上限;原來的上限可能記錄了專案已知的不相容邊界。

相依版本範圍還可能受到其他套件、Python 版本和平台條件限制。 發生衝突時,應從解析錯誤中找出互相矛盾的要求。 修改方法和相依分組見 相依管理文件。

全面升級適合獨立維護時段

更新整個專案的指令是:

1
2
3
4
uv lock --upgrade
git diff --stat
git diff -- uv.lock
uv sync --locked

全面升級適合相依維護任務,但不適合混進原本只修改頁面文字的提交。 變更越大,發現故障後越難判斷是哪個套件引起的。

建議先更新一個應用相依套件並執行驗收,再單獨處理開發工具。 對於具有原生擴充、GPU 執行階段或模型推論後端的專案,還要檢查系統函式庫與驅動程式要求。 鎖定檔能記錄套件解析結果,卻不能取代實際設備上的執行驗證。

–locked 和 –frozen 怎麼選

這兩個參數都經常出現在部署指令中,但檢查程度不同。

指令 行為 適用情況
uv lock --check 檢查鎖定檔是否與宣告一致 提交前檢查
uv sync --locked 要求鎖定檔有效,再同步環境 部署和重現
uv run --locked python main.py 要求鎖定檔有效,再執行 日常驗證
uv sync --frozen 使用現有鎖定檔,略過是否過期的檢查 已由其他步驟驗證鎖定檔的流程

如果你改了相依宣告,卻忘記更新鎖定檔,--locked 能幫助發現問題。 用 --frozen 略過檢查,並不能說明這次宣告已經生效。

另一個差異在於環境清理:uv sync 預設精確同步,會移除鎖定檔以外的套件。 因此手動向 .venv 暫時安裝的除錯套件,下次同步後可能消失。 應保留的開發工具要透過 uv add --dev 寫入宣告。

升級後用小測試檢查關鍵行為

建立 test_main.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import requests


def test_prepare_request_keeps_query_parameter():
    prepared = requests.Request(
        "GET",
        "https://example.com/search",
        params={"q": "hello world"},
    ).prepare()
    assert prepared.method == "GET"
    assert prepared.url == "https://example.com/search?q=hello+world"

執行:

1
2
3
4
uv lock --check
uv run --locked pytest -q
uv run --locked python main.py
git diff --check

這個測試涵蓋請求參數編碼這項具體行為。 它不能證明網路連線、代理、TLS 或應用介面都正常。 實際專案應補上自己的關鍵路徑,例如文件解析結果、資料庫讀寫或介面回應結構。

如果專案使用 MinerU 解析文件,可以選一份固定 PDF,比較升級前後的頁數、表格和圖片引用。 把小樣本保留為迴歸測試輸入,比只檢查 import 成功更有判斷力。

更新失敗後如何回復

先保留錯誤紀錄和差異,確認是否存在這次升級以外的工作。 下面的指令會捨棄這兩個檔案中未提交的修改,僅適合它們的變化全部屬於這次升級時使用。

1
2
3
4
git diff -- pyproject.toml uv.lock
git restore --source=HEAD -- pyproject.toml uv.lock
uv sync --locked
uv run --locked pytest -q

同時回復宣告與鎖定檔,可以避免兩者互相矛盾。 同步後再次執行測試,確認回復的是可用狀態,而不只是檔案看起來一樣。

如果升級已經提交,應先找出已知可用的提交,再選擇對應檔案版本或撤銷升級提交。 不要直接複製同事的 .venv:環境路徑、平台二進位檔和直譯器版本都可能不一致。

相依套件回復也不會自動撤銷資料庫遷移或程式執行後產生的資料變化。 升級涉及資料格式時,需要應用程式自己的備份與還原方案。

只有 requirements.txt 時怎麼辦

先判斷你是想繼續維護 requirements 流程,還是正式遷入 uv 專案。 這兩個目標不應該在一個升級指令中混著完成。

保留原有流程時,可在單獨的虛擬環境中安裝:

1
2
uv venv
uv pip install -r requirements.txt

如果 requirements 已經精確固定版本,這條安裝指令不會自動解除限制。 要遷入專案工作流程,可以在遷移分支初始化專案,再匯入相依套件:

1
2
3
uv init --bare
uv add -r requirements.txt
uv lock --check

匯入一份 pip freeze 匯出的檔案,可能把間接相依套件也變成直接宣告。 遷移後應逐項區分應用程式實際使用的套件和其他套件帶來的相依項目。 私有來源、可編輯安裝和平台條件需要另行核對,詳見 官方遷移指南。

為仍使用 pip 的部署流程匯出相依套件

專案暫時不能全部切換到 uv 時,可以從鎖定檔匯出:

1
uv export --locked --format requirements.txt --no-dev --output-file requirements.txt

該檔案應視為鎖定檔的衍生產物。 修改相依套件後先更新專案與鎖定檔,再重新匯出,避免同時人工維護兩套版本清單。

範例專案沒有封裝自身;可安裝的應用專案還需檢查匯出檔案中是否包含專案本身或本機路徑引用。 部署時必須確保對應原始碼存在,不能假設只複製 requirements 就夠了。 匯出選項見 官方匯出文件。

常見問題快速定位

現象 優先檢查 處理方向
sync 後版本沒有變化 鎖定檔已有可用版本 明確執行單一套件升級
upgrade 後仍是舊版本 精確限制或其他套件限制 閱讀解析結果,評估後調整宣告
終端機成功,編輯器匯入失敗 Python 直譯器路徑 選擇專案 .venv
鎖定檔正確但安裝失敗 網路、憑證、磁碟、平台 wheel 保留錯誤資訊,按下載或建置階段排查
部署提示鎖定檔過期 宣告與鎖定檔是否一起提交 在開發分支更新並驗證鎖定檔
同步後暫時工具消失 工具是否寫入 dev 相依套件 使用 uv add --dev 管理

更新相依套件的完成標準是:宣告清楚、鎖定檔一致、安裝環境正確,而且關鍵應用行為通過驗證。 確定升級對象後,優先從一個套件開始,保留差異和回復方式。