diff --git a/20.01. Programming/Python/uv.md b/20.01. Programming/Python/uv.md index 38fda02..36774ca 100644 --- a/20.01. Programming/Python/uv.md +++ b/20.01. Programming/Python/uv.md @@ -6,10 +6,266 @@ time: 20:54:21 description: --- -# Install -- [Installation | uv](https://docs.astral.sh/uv/getting-started/installation/#standalone-installer) +# Install uv +依官方的步驟來安裝 [Installation | uv](https://docs.astral.sh/uv/getting-started/installation/#standalone-installer)。 +# 管理 Python 版本 +## 列出可安裝的 Python 版本 +用 [`uv python list`](https://docs.astral.sh/uv/reference/cli/#uv-python-list) 可以列出可安裝的 Python 版本。 +```bash +❯ uv python list +cpython-3.14.0a5+freethreaded-windows-x86_64-none +cpython-3.14.0a5-windows-x86_64-none +cpython-3.13.2+freethreaded-windows-x86_64-none +cpython-3.13.2-windows-x86_64-none +cpython-3.12.9-windows-x86_64-none +cpython-3.11.11-windows-x86_64-none +cpython-3.10.16-windows-x86_64-none +cpython-3.9.21-windows-x86_64-none +cpython-3.8.20-windows-x86_64-none +cpython-3.7.9-windows-x86_64-none +pypy-3.11.11-windows-x86_64-none +pypy-3.10.16-windows-x86_64-none +pypy-3.9.19-windows-x86_64-none +pypy-3.8.16-windows-x86_64-none +pypy-3.7.13-windows-x86_64-none +``` +## 安裝 Python +使用 [`uv python install `](https://docs.astral.sh/uv/reference/cli/#uv-python-install) 可以安裝指定的版本,例: +```shell +uv python install 3.9 3.11 3.13 +``` +這樣就會安裝 `3.9`、`3.11`、`3.13` 這三個版本。 + +如果 `uv python install` 沒有指定版本的話,就會安裝目前能下載的最新版本。 + + +## 移除 Python +用 `uv python uninstall ` 來移除一個或多個 Python 版本,`` 一定要給。 + + +## Python 安裝路徑 +[`uv python dir`](https://docs.astral.sh/uv/reference/cli/#uv-python-dir) 會列出目前已安裝的 Python 路徑。 + + +# 專案管理 +## 單一檔案的專案 +先從簡單的開始,如果你寫了有一個檔案,可以用 uv 來管理它,當你把它 copy 給人的時候,只要用 [`uv run `](https://docs.astral.sh/uv/reference/cli/#uv-run) ,uv 就可以幫你完成相依套件的安裝,讓檔案可以順利執行。 + +先從建立檔案開始,例: +```shell +uv init --python 3.11 --script hello.py +``` + +這邊我們讓 uv 幫我們建立 `hello.py` 這個檔案,使用的環境是 Python 3.11。如果你沒有安裝 Python 3.11 ,那麼 uv 會自動幫你安裝,很方便吧。 +`hello.py` 的內容: +```python +# /// script +# requires-python = ">=3.11" +# dependencies = [] +# /// + + +def main() -> None: + print("Hello from hello.py!") + + +if __name__ == "__main__": + main() +``` + +前4行就是給 uv 看的 metadata,uv 靠它來維護執行環境與套件。 + + +### 安裝套件 +使用 [`uv add`](https://docs.astral.sh/uv/reference/cli/#uv-add) 來安裝套件,假設我們需要使用 `rich` 這個套件: +``` +> uv add rich --script hello.py +Updated `hello.py` +``` + +hello.py 的內容會變成: +```python +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich", +# ] +# /// + + +def main() -> None: + print("Hello from hello.py!") + + +if __name__ == "__main__": + main() +``` + +可以看到 dependencies 增加了 rich 套件。之後你將 `hello.py` 傳給別人,那人只需要用 `uv run hello.py`,uv 就會自動安裝需要的 Python 版本與相依套件。 + + +### 移除套件 +用 [`uv remove`](https://docs.astral.sh/uv/reference/cli/#uv-remove) 可以移除套件,例如 `uv remove rich --script hello.py`。這樣就可以讓 `hello.py` 不再需要 rich 套件。 + + +## 資料夾的專案 +實務上單一檔案還是不方便,uv 管理資料夾是用 [`uv init`](https://docs.astral.sh/uv/reference/cli/#uv-init),例: +``` +uv init hello_uv --python 3.13 +``` + +uv 會建立 hello_uv 資料夾,Python 版本是 3.13。 +資料夾的內容會有: +``` +.git +.gitignore +.python-version +main.py +pyproject.toml +README.md +``` + +- `.git`, `.gitignore`: uv 會自動建立 git repo,但是還沒 commit。 +- `.python-version`: 這個專案使用的 Python 版本,如果你在 `uv init` 的時候沒有指定 Python 版本,那麼就會用**已安裝的最高版本**。 +- `main.py`: 你的程式 +- `pyproject.toml`: `pyproject.toml`是 [PEP 518](https://peps.python.org/pep-0518/) 與 [PEP 621](https://peps.python.org/pep-0621/) 中提出的標準,用來定義 Python 的執行環境的設定檔 + + +### 執行檔案 +一樣用 `uv run` 就可以執行,例:`uv run main.py`。 +在 `uv run` 執行過後,會多出一個 `uv.lock` 的檔案,這個檔案由 uv 管理(`uv add`會用到),`uv.lock` 基本上就是 `pyproject.toml` 的內容,uv 根據這個檔案來管李執行環境與套件。 + + +### 安裝套件 +在 uv 管理的資料夾內安裝套件有2個方式,`uv pip install` 與 `uv add`。 + + +#### `uv add` +例如我們用 `uv add` 安裝 rich 這個套件: +```shell +uv add rich +``` + +uv 會幫你修改 `pyproject.toml` 與 `uv.lock`。 + +`pyproject.toml` 的內容會變成: +``` +[project] +name = "hello-uv" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "rich>=13.9.4", +] +``` + +dependencies 會多出 rich 套件以及版號。 + +而 `uv.lock` 也會同步修改,內容如下: +``` +version = 1 +revision = 1 +requires-python = ">=3.13" + +[[package]] +name = "hello-uv" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "rich" }, +] + +[package.metadata] +requires-dist = [{ name = "rich", specifier = ">=13.9.4" }] + +// 略 + +[[package]] +name = "rich" +version = "13.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +// 略 +``` + +這樣屆時你將資料夾分享出去,只要用 `uv run` 就可以了,uv 會自動安裝相應的環境與套件,很方便。 + + +#### `uv pip` +`uv pip` 就很單純,它就是幫你裝套件而已,在 `pyproject.toml` 與 `uv.lock` 內都不會有紀錄。 + + +### 移除套件 +使用 `uv add` 安裝的套件就用 `uv remove` 來移除。 +使用 `uv pip install` 安裝的套件就用 `uv pip uninstall` 來移除。 + + +#### `pyproject.toml` 被修改了怎麼辦? +先執行 `uv lock` 來將 `pyproject.toml` 的內容更新到 `uv.lock` ,再執行 `uv sync` 來更新環境與套件。 + + +# 方便的 `uv tool` +## 安裝工具 +之前安裝的套件都是給某個檔案或是資料夾使用,但是 Python 世界裡有些套件是可以單獨使用的,像是 yt-dlp 可以在命令列當作一個工具來用: +``` +yt-dlp https://www.youtube.com/watch?v=111 +``` + +這時候就可以用 `uv tool install yt-dlp` ,uv 會建立一個環境專供 yt-dlp ,不用怕污染到其他專案。 +安裝好之後,yt-dlp就可以直接使用了。 + + +## 移除工具 +`uv tool uninstall ` 可以移除工具(套件)。 + + +## 更新工具 +`uv tool upgrade ` 可以更新工具(套件)。 + + +## 工具安裝位置 +`uv tool dir` 會列出工具安裝路徑。 + + +# 用 uv 執行 `.py` +這邊的`.py` 檔是指沒有被 uv 管理的檔案,假設你拿到一個檔案 `test.py`,你可以用 uv 來指定 Python 版本與套件來執行它。 +先從最簡單的開始,例: +``` +uv run test.py +``` + +uv 會找一個 Python 版本來執行它。uv 挑選 Python 版本的規則是這樣: +1. 如果目前目錄有 `.python-version`,而且裡面有版號,那就用這一版來執行。 +2. 目前已經有啟用了某個虛擬環境,那就用這個虛擬環境來執行。 +3. 目前的目錄有 `.venv` 這個資料夾,那就用`.venv` 這個資料夾裡面紀錄的版號來執行。 +4. uv 已安裝的最高版本。 +5. 目前環境有能找到的第一個 Python 執行檔。 + +當然你也可以指定一個 Python 版本來執行: +``` +uv run --python 3.11 test.py +``` + +如果指定的版本沒有安裝,uv 會自動安裝。 + +如果檔案裡面有需要安裝的套件,也可以寫出需要的套件,使用 `--with` 參數: +``` +uv run --python 3.11 --with rich test.py +``` + +uv 會建立一個臨時的虛擬環境,幫你安裝 rich 套件,並執行 `test.py`。 + +## 管理臨時的虛擬環境 +用 `uv cache dir` 列出臨時的虛擬環境的路徑。 +用 [`uv cache clean`](https://docs.astral.sh/uv/reference/cli/#uv-cache-clean) 清除臨時的虛擬環境。 + # 參考來源 \ No newline at end of file