老王 Good youtube to explain conda, uv difference https://www.youtube.com/watch?v=jd1aRE5pJWc&ab_channel=%E7%A8%8B%E5%BA%8F%E5%91%98%E8%80%81%E7%8E%8B

very good follow-up by 老王 https://www.youtube.com/watch?v=-MSLJKjH8U0&ab_channel=%E7%A8%8B%E5%BA%8F%E5%91%98%E8%80%81%E7%8E%8B

[@liaoPythonImport2020] 指出 import 常常遇到的問題

[@loongProjectStructure2021] Python project structure 寫的非常好,本文直接引用自己參考。

GitHub - karpathy/minbpe: Minimal, clean code for the Byte Pair Encoding (BPE) algorithm commonly used in LLM tokenization.

UV vs. Conda/Mamba

uv 和 conda/mamba 都包含 virtual environment 和 package dependency management, 但是代表兩個不同的派別。

uv: local virtual environment: .venv, install package 非常快。而且可以做現代 python project management, i.e. pyproject.toml.

conda/mamba: global virtual enviornment: conda 非常慢,但是 mamba 非常快!缺點是無法做 python project management. 解法: 用 mamba 取代 conda. 但似乎無法解決 python project management?

(2025/8/16) uv 從 local 變 global

第一個問題, why? 因爲不會占用太多資源。local package 無法 cross-platform, like PC with CUDA and Mac.

UV has a global cache system that can help with both issues. You can configure it to use a shared cache location:

1. Use UV’s global cache to avoid duplicate downloads

1
2
3
4
5
6
7
8
# Set UV to use a global cache directory
export UV_CACHE_DIR="$HOME/.cache/uv"  # Linux/Mac
# or on Windows: set UV_CACHE_DIR=%USERPROFILE%\.cache\uv

# Then use UV with --system or create virtual environments outside project
uv venv --python 3.11 ~/.venvs/myproject
source ~/.venvs/myproject/bin/activate  # Linux/Mac
# or Windows: ~/.venvs/myproject/Scripts/activate

2. Generate Platform-Specific Lock Files

使用同一個 pyproject.toml, 但是產生不同的 lock files. 然後用 uv sync –active 在各自的 global virtual enviornment.

uv lock and uv.lock

uv lock 產生 uv.lock file.
uv.lock 的角色

  • 類似於 requirements.txt,但更完整,精確記錄實際安裝的版本與依賴樹
  • 還會包含 跨平台資訊(不同作業系統與 Python 版本的 resolution 結果)。
  • 不要直接編輯 uv.lock,正確做法是修改 pyproject.toml 或需求檔,再透過 uv lock 來更新。
1
2
3
# Generate platform-specific lock files
uv lock --platform linux-x86_64    # For CUDA systems in wsl or native ubuntu
uv lock --platform darwin-arm64     # For Mac M1/M2

uv sync 的幾種模式

接下來是最 confusing 的部分。先說結論: 對於 global environment, 使用 uv sync --active, 對於自己的 local environment, 使用 uv sync, 對於 clone 別人的 project, 使用 uv sync --frozen.

flowchart TD
    A["要同步哪裡?"] --> B["Global (全域環境)"]
    A --> C["Local env (專案 venv)"]

    B --> D{"使用已啟動的環境嗎?"}
    D -->|Yes| E["uv sync --active"]

    C --> F{"是自己的專案嗎?"}
    F -->|Yes| G["uv sync (預設模式)"]
    F -->|No| H["uv sync --frozen"]

使用情境 指令 說明
Global environment(例如你想把全域 Python 環境的套件和 uv.lock 同步) uv sync --active 會將目前「已啟動」的環境(例如全域 Python、或 venv/conda)與 uv.lock 中的套件同步
Local environment(自己開發的專案) uv sync 預設會依據 uv.lock 建立或更新本地的 .venv/
Clone 別人的專案,要確保環境完全一致 uv sync --frozen 嚴格依照 uv.lock,不會重新解析依賴。若 uv.lock 不符合當前環境,會直接失敗(避免偷偷 drift)

另外還有 uv sync --lockeduv sync --frozen 類似但不同。見 Appendix A.

uv sync --locked vs --frozen 的關鍵差異

1
1
uv sync --locked  # 要求 uv.lock 必須是最新的,否則失敗
  • 檢查 lockfile 是否最新:確保 uv.lockpyproject.toml 同步
  • 如果過期會失敗:如果 lockfile 過期,命令會報錯退出
  • 適用場景:CI/CD 環境,確保依賴完全一致
1
1
uv sync --frozen   # 直接使用 uv.lock,不檢查是否最新

“To use the lockfile without checking if it is up-to-date, use the –frozen option”

  • 不檢查 lockfile 狀態:直接使用現有的 uv.lock,不管是否過期
  • 不會重新鎖定:完全按照現有 lockfile 安裝
  • 適用場景:Docker 建構、生產部署

3. Add UV cache directories to .gitignore 這是 in case commit local cache.

注意要使用 .uvignore.gitignore 以免 check-in 一堆 packages.

1
2
3
4
5
# Add to .gitignore
.venv/
.uv/
__pycache__/
*.pyc

(2025/8/8) Conda 轉 Mamba takeaway

from 5分钟彻底搞懂!Anaconda Miniconda conda-forge miniforge Mamba

  1. 以後千萬不要 install anaconda, 只要 install miniforge!
  2. 使用 miniforge 的 mamba 取代 anaconda 的 conda! 速度快十倍!
  3. 對於已經 install anaconda
    1. conda install mamba -n base -c conda-forge

    2. edit ~/.bashrc, 加上 eval "$(mamba shell hook --shell bash)"

    3. source ~/.bashrc, 以後把 conda command 改成 mamba command! ```bash

      »> conda initialize »>

      !! Contents within this block are managed by ‘conda init’ !!

      __conda_setup=”$(‘/home/allen/anaconda3_25/bin/conda’ ‘shell.bash’ ‘hook’ 2> /dev/null)” if [ $? -eq 0 ]; then eval “$__conda_setup” else if [ -f “/home/allen/anaconda3_25/etc/profile.d/conda.sh” ]; then . “/home/allen/anaconda3_25/etc/profile.d/conda.sh” else export PATH=”/home/allen/anaconda3_25/bin:$PATH” fi fi unset __conda_setup

      «< conda initialize «<

»> mamba initialize »>

Initialize mamba shell for bash

eval “$(mamba shell hook –shell bash)”

«< mamba initialize «<

1
2
3
4
5
6
7
8
9
10
11
12

![[Pasted image 20250809162554.png]]



## Modern Python Project

以下我們用 Karpathy 的 minbpe 爲例。
先從 github 下載 minbpe.  
用 tree 看結構。
用 pytest 確認是否 ok.

$ git clone https://github.com/karpathy/minbpe.git $ tree . ├── minbpe │   ├── init.py │   ├── base.py │   ├── basic.py │   ├── gpt4.py │   └── regex.py ├── minbpe.egg-info │   ├── PKG-INFO │   ├── SOURCES.txt │   ├── dependency_links.txt │   └── top_level.txt ├── pyproject.toml ├── requirements.txt ├── setup.py ├── tests │   ├── init.py │   ├── taylorswift.txt │   └── test_tokenizer.py └── train.py

$ pytest collected 21 items tests/test_tokenizer.py …….. [100%] ============= 21 passed in 22.04s ===

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

## 緣起 (2025/7/31)

Youtube video 解釋很好。第一個 project management 需求是: 
1. Virtual environment (project 隔離) + 
2. Package management (**萬惡根源!installation 以及不同版號之間的 dependency** )

## Virtual environment 三種選擇 : 用 `uv venv` or `conda create`

1. **Python 內建的在  local virtual environment .venv directory => 不好用 DO NOT use!
- 是 Python 3.3+ 內建的輕量 virtual environment 工具(官方標準庫提供)。  

2. **`uv venv`**  
- 一個結合傳統 local`.venv` 現代輕量 virtual environment 和 package management 工具。  
- 操作快速且用戶體驗好,功能類似於 pip + virtualenv + pyenv 的整合。 **=> 對於動態專案非常有用,例如搭配 Claude Code 很方便。**
- 容易建立和管理 virtual environments,與 Python 生態系統工具整合良好。  

3. **`Conda create`**  
- 一個支援多語言(Python、R、Julia等)且功能完整的環境及套件管理器。  
- 較 uv重且使用資源較多,**global environment (~/anaconda3) 不 tie to specific project。**  
- 非常適合資料科學專案、穩定且需要多語言或複雜依賴的專案。套件管理不只限 Python,還包含系統函式庫及執行檔。

| 特性             | `.venv` (builtin)      | `uv venv`                | `Conda create`        |
| -------------- | ---------------------- | ------------------------ | --------------------- |
| **範圍 (Scope)** | Python,local prj/.venv | Python,local prj/.venv   | 多語言,global ~/anaconda |
| **安裝複雜度**      | 簡單,內建工具                | 簡單且現代化                   | 較複雜且資源需求較高            |
| **套件管理**       | pip(獨立工具)              | 與 pip 整合                 | 整合 conda              |
| **效能**         | 輕量且基本                  | 快速且高效                    | 較慢且資源密集               |
| **適用場景**       | 簡單 isolated Python 專案  | 動態專案,快速設置                | 資料科學,穩定或多環境需求         |
| **跨版本支援**      | 較有限(單一 Python 版本)      | 支援多 Python 版本            | 支援多語言版本               |
| **進階功能**       | 較少                     | 結合 venv + pyenv + pip 功能 | 豐富,支援 binaries 及系統函式庫 |


## Package management

包含 package installation (安裝) 和 package list/dependency resolution (依賴解決)
### Package Installation 建議用 `uv pip install`

Installation 基本很單純:`pip install` or `uv pip install` or   `conda install`.   

pip 是 Python 官方推薦的標準套件安裝工具,適用於一般軟體開發。而 Conda 主要針對資料科學和多語言需求,並且能安裝一些系統層級依賴或非 Python 套件。

- **pip install 是最普遍的方式。**  
  大部分 Python package(尤其在 PyPI 上的)都能用 pip 安裝,且版本更新快。  
- **pip 通用於所有 virtual environment(.venv, uv, Conda env 等),而且大多數工具都是用 pip 作為安裝工具。**  
- **Conda install 只能用在 Conda 環境中,且只能安裝 Conda repository 中的 packages(也可以透過 conda-forge 獲取較多套件)。**  
- **此外,pip 支援從多種來源安裝(PyPI、Git repo、local package 等),彈性很高。**



**`uv pip install` 和傳統的 `pip install` 在功能上類似,都是用來安裝 Python 套件,但兩者的實現和行為有顯著差異:**

| 差異點              | `uv pip install`                                   | `pip install`                                |
|--------------------|--------------------------------------------------|---------------------------------------------|
| **性能與速度**       | 基於 Rust 實作,支持平行下載與安裝,速度快 10-100 倍 | 實現較老,單線程下載,速度較慢               |
| **虛擬環境管理**     | uv 內建虛擬環境管理,安裝時會自動識別並使用專案虛擬環境 | 需手動切換激活虛擬環境,pip 本身不管理環境    |
| **依賴解析**         | 使用優化過的依賴解決算法,錯誤訊息更清晰,衝突處理較好  | 解析能力較弱,衝突時錯誤不易理解             |
| **安裝行為**         | 會嚴格執行 `--only-binary` 等限制,對直接 URL 安裝更嚴格  | 對 URL 安裝較寬鬆,有時從源碼編譯             |
| **工具整合性**       | 與 uv 生態系統深度整合,支持虛擬環境、依賴鎖定、版本管理  | 只負責單純安裝套件,環境及鎖定需其他工具協助   |
| **錯誤處理與訊息**   | 清晰且具體,便於排錯                                | 較一般,錯誤提示有時不夠詳細                   |
| **安裝目標環境**     | 可針對指定虛擬環境安裝(非必須當前環境)               | 僅在當前激活的環境中安裝                      |

**重點說明:**

- `uv pip install` 實際上是 uv 對 pip 安裝功能的包裝與加強版,保留 pip 的用法與相容性,但加快速度並完善依賴解決和環境管理[1][2][6][5]。  
- `pip install` 是 Python 標準的套件安裝工具,廣受使用但功能專注且性能有限,需要搭配其他工具才能完善開發流程[1][5]。  
- 使用 `uv pip install` 在 uv 管理的專案中能更好地與虛擬環境和鎖定檔同步,適合追求效率和一致性的現代開發流程[1][6]。

如你主要在使用 uv 作為專案工具,建議改用 `uv pip install` 來享受快速且整合的體驗;但在傳統環境或無 uv 支援時,仍可用 `pip install`。


### 進階: Package Dependency 建議用 pyproject.toml + uv

Python 最令人詬病的地方是長期以來沒有一套官方完整且優良的 dependency management,造成很多包版本衝突及不可控問題。

**requirements.txt**:  
-  簡單易用以前最常用的方法,是過去最常見記錄依賴的格式。但它僅列出已安裝的 package 名稱與版本(通常手動維護),不描述 package 之間的依賴樹狀關係。 
- requirements.txt 是靜態列出安裝套件名及版本的檔案,無法描述完整依賴樹,卸載時無法自動清理依賴,且無法做依賴衝突解析;
- 適用作快速部署的“套件快照”,而非規劃完全版的依賴樹。  

**pyproject.toml**:  
- pyproject.toml 為 Python 官方新標準,可清楚聲明專案的直接依賴及建置工具版本。  
- 現代工具如 Poetry、PDM、Flit 等都使用 pyproject.toml,能有效管理依賴並支持依賴衝突解決,使環境乾淨且可重現。  
- 建議現代專案採用 pyproject.toml 結合專門依賴管理工具,以提升可維護性與穩定性。

### 建議說明
- **pip 自身並沒有內建依賴解決功能**(至少到 pip 22.x 版本前是如此,近期已有部分改進,但仍不及 Poetry 這類工具)。依賴解決常由外部管理工具(Poetry、uv、PDM、pip-tools)來輔助,而這些工具多是以 `pyproject.toml` 為標準依據。  
- **Conda 內建依賴解決,能安裝非 Python 套件和系統依賴,適合科學計算、跨語言專案。**  
- **pip + requirements.txt 仍然是大部分已有專案和 CI/CD 主要使用的方式,但逐漸被 pyproject.toml + Poetry/uv 類工具取代。**

## uv 建立並管理虛擬環境與 Python 專案 (含 pyproject.toml)

結合 **uv** 進行管理虛擬環境並建立 Python 專案(含 `pyproject.toml`)的完整流程:

1. **安裝 uv**

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
# 或在 macOS/Linux 用 brew 安裝
brew install uv
  1. 建立新的 Python 專案(包含 pyproject.toml)
1
2
uv init my_project
cd my_project

此時 uv 會建立以下基本專案結構(含 pyproject.toml):

1
2
3
4
5
6
my_project/
├── .gitignore
├── .python-version
├── README.md
├── main.py
└── pyproject.toml
  1. 建立虛擬環境
1
uv venv
  • 這會在專案目錄下建立 .venv 虛擬環境資料夾(名稱可自訂,預設是 .venv)。
  • uv 也支援使用指定 Python 版本(如果沒裝,會自動下載):

    1
    uv venv --python 3.12.0
    
  1. 安裝或新增套件(並自動更新 pyproject.toml

例如安裝 requests

1
uv add requests
  • 這會在虛擬環境中安裝 requests,同時將依賴加入 pyproject.toml 的 dependencies。
  1. 執行 Python 腳本
1
uv run main.py
  • 會自動使用專案裡的虛擬環境執行。
  1. 鎖定依賴版本
1
uv lock
  • 生成或更新 uv.lock 文件,確保版本一致。
  1. 同步安裝所有依賴

若其他人拉取專案,或剛從版本庫複製專案,可用:

1
uv sync
  • 根據 uv.lockpyproject.toml 安裝所有需依賴。

流程總結示意

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 安裝 uv(若需)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 新建專案
uv init my_project
cd my_project

# 建立虛擬環境(可指定 Python 版本)
uv venv --python 3.12.0

# 新增依賴
uv add requests flask

# 鎖定版本
uv lock

# 執行程序
uv run main.py

# 同步安裝依賴(他人複製代碼後用)
uv sync

補充說明

  • uv init 會自動幫你生成 pyproject.toml,並載入一份簡單的專案結構。
  • 虛擬環境 .venv 不會在 uv init 時自動建立,需要用 uv venv 指令生成。
  • uv add 會同時安裝套件及更新 pyproject.toml,保持依賴同步管理。
  • uv run 會自動找到並使用虛擬環境,免去手動 activate 的麻煩。
  • uv lockuv sync分別用於鎖版本和同步安裝,非常適用協作時保持環境一致性。

### uv add package 還是 uv pip install package?

  • uv add package
    • 是一個「高階的專案管理 API」。
    • 它會將該套件自動加入你的專案的 pyproject.toml 中的依賴清單,同時安裝套件。
    • 適合你有使用 pyproject.toml 來聲明專案依賴的情況。
    • 這樣做有利於保持依賴的有序管理與版本鎖定,進而方便團隊同步。
    • uv add 執行時會產生或更新 uv.lock 鎖定檔,確保環境跨機相容。
    • 簡言之,是 uv 推薦的「專案依賴管理」方式。
  • uv pip install package
    • 是一個「低階的 pip 兼容 API」,等同於傳統的 pip install
    • 僅僅在當前虛擬環境中安裝套件,不會改動 pyproject.toml
    • 適合臨時安裝或不使用 pyproject.toml 管理依賴的場景。
    • 這種用法類似傳統直接操作環境的方式,缺少專案層級的依賴追蹤。

簡單比喻:

功能 uv add uv pip install
依賴管理 自動更新 pyproject.toml 不更新配置文件
配合 pyproject.toml 是(適合有專案依賴聲明) 否(手動操作當前環境)
適合用途 正規專案依賴管理與團隊協作 臨時、低階操作或快速安裝
產生鎖定檔 更新 uv.lock 不產生鎖定檔
  • uv add 會保證跨平台(Windows、Linux 等)相容性,選擇版本時更謹慎,能確保其他人也可以無差異環境重現。
  • uv pip install 則通常安裝最新版本(無跨平台版本限制),有時可能帶來不一致版本風險。
  • uv add 是「專案 API」,而 uv pip install 是「低階 pip 命令集」的替代方案。

結論建議:

  • 如果你在用 pyproject.toml 管理專案,請優先使用 uv add package。這能讓專案依賴管理更規範且適合團隊合作。
  • 如果只是臨時在某環境裝包,或不想改動依賴聲明,可以用 uv pip install package

這樣能兼顧依賴管理的乾淨與裝包靈活度。

uv 設定

uv stores packages is important for cross-platform development. Here’s how uv works:

Where uv stores packages:

1. Virtual Environment (.venv directory)

1
2
3
4
5
your-project/
├── .venv/           # Virtual environment (should NOT be synced)
├── pyproject.toml   # Project config (SHOULD be synced)
├── uv.lock         # Lock file (SHOULD be synced)
└── your-code/

2. Global package cache (shared across projects)

  • Linux/Mac: ~/.cache/uv/
  • Windows: %LOCALAPPDATA%\uv\cache\

Best practices for Google Drive sync:

✅ DO sync these files:

1
2
3
4
# Add to your project (sync these)
pyproject.toml      # Project dependencies and config
uv.lock            # Exact versions for reproducibility
requirements.txt    # If you're using this instead

❌ DON’T sync these:

1
2
3
4
5
# Add to .gitignore (don't sync these)
.venv/             # Virtual environment
__pycache__/       # Python cache
*.pyc              # Compiled Python files
.pytest_cache/     # Pytest cache

1. Create a .gitignore file in your project:

1
2
3
4
5
6
7
8
9
10
# Create .gitignore to prevent syncing unwanted files
cat > .gitignore << 'EOF'
.venv/
__pycache__/
*.pyc
*.pyo
.pytest_cache/
.coverage
*.egg-info/
EOF

2. Use pyproject.toml for dependency management:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# pyproject.toml (this gets synced)
[project]
name = "claude_mt_bench"
dependencies = [
    "torch",
    "pytest",
    "accelerate",
    # other dependencies
]

[tool.uv]
dev-dependencies = [
    "pytest",
]

3. On each computer, recreate the environment:

1
2
3
4
# On any computer (PC/Mac), run:
cd ~/gdrive/github/claude_mt_bench
uv venv        # Creates local .venv (not synced)
uv sync        # Installs dependencies from pyproject.toml

For your current situation:

Since you’re already using Google Drive sync, here’s what to do:

1
2
3
4
5
6
7
8
9
10
11
12
# 1. Make sure .venv is not being synced
echo ".venv/" >> .gitignore

# 2. If .venv already exists and is being synced, delete it
rm -rf .venv/

# 3. Create fresh environment on each machine
uv venv
uv sync  # or uv add your-dependencies

# 4. Run tests
uv run pytest tests/ -v

This way, each computer maintains its own .venv directory locally, but your project configuration is synced via pyproject.toml. The environments are isolated and won’t conflict between different operating systems.

Cross-platform 挑戰

  1. Share 同一個 project with different PCs and Mac. 有些 PC 有 GPU with different CUDA 版本。 Mac 則需要 run CPU 版本。

如果你有兩台電腦共用同一個專案目錄,一台用 CPU 版本的 PyTorch,另一台用 CUDA 版本,要如何在 requirements.txt、pyproject.toml 或其他方式管理這種差異,核心問題是「依賴版本與來源有所不同怎麼條件安裝並共存」。

整理並參考最新的實務建議與工具支持,說明如下:

1. requirements.txt

  • 傳統 requirements.txt 只是單純列出套件名和版本,不支援根據硬體或環境條件切換版本

  • 你可以寫兩份 requirements-cpu.txtrequirements-gpu.txt,兩台電腦各自用對應檔案安裝套件:

    text

    # requirements-cpu.txt torch==2.0.1+cpu torchvision==0.15.2+cpu

    text

    # requirements-gpu.txt torch==2.0.1+cu118 torchvision==0.15.2+cu118

  • 安裝時指定檔案,例如:pip install -r requirements-cpu.txt。但只能靠手動選擇檔案,不會自動根據硬體條件切換。

2. pyproject.toml + Poetry 或 uv

現在多數現代 Python 專案用 pyproject.toml 配合管理工具(Poetry、uv、PDM)管理依賴,更靈活支持根據系統條件安裝版本。

a. Poetry 支援「依賴群組」與「條件裝載」示例

text

[tool.poetry.dependencies] python = "^3.8" [tool.poetry.group.cpu] optional = true [tool.poetry.group.cpu.dependencies] torch = { version = "^2.0.1", source = "pypi", markers = "sys_platform != 'linux' and sys_platform != 'win32'" } torchvision = { version = "^0.15.2", source = "pypi", markers = "sys_platform != 'linux' and sys_platform != 'win32'" } [tool.poetry.group.gpu] optional = true [tool.poetry.group.gpu.dependencies] torch = { version = "^2.0.1+cu118", source = "torch_cuda", markers = "sys_platform == 'linux' or sys_platform == 'win32'" } torchvision = { version = "^0.15.2+cu118", source = "torch_cuda", markers = "sys_platform == 'linux' or sys_platform == 'win32'" } [[tool.poetry.source]] name = "torch_cuda" url = "https://download.pytorch.org/whl/cu118" priority = "explicit"

  • 你可用命令選擇性安裝:

    bash

    poetry install --with cpu poetry install --with gpu

  • 但實務上系統判斷和混合安裝稍複雜,需要人工選擇。

b. uv 配置範例(根據系統條件切換索引源與版本)

pyproject.toml 範例(摘自 uv 文檔):

text

[project] name = "my_project" version = "0.1.0" requires-python = ">=3.12.0" dependencies = [ "torch>=2.7.0", "torchvision>=0.22.0", "pytorch-triton-rocm>=3.3.0 ; sys_platform == 'linux'", ] [tool.uv.sources] torch = [ { index = "pytorch-rocm", marker = "sys_platform == 'linux'" }, ] [[tool.uv.index]] name = "pytorch-rocm" url = "https://download.pytorch.org/whl/rocm6.3" explicit = true

  • 可針對各平臺分別設定不同索引和版本條件安裝。

  • uv 能根據作業系統自動選擇對應版本,較適合跨平台 GPU/CPU 自動處理。

3. 用環境變數或安裝腳本動態決定依賴

  • 實務中,有些團隊會撰寫安裝腳本判斷是否有 GPU,然後用不同指令安裝相應版本,避免在套件定義檔內複雜判斷。

  • 例如 bash 下:

    bash

    if nvidia-smi >/dev/null 2>&1; then pip install torch==2.0.1+cu118 torchvision==0.15.2+cu118 -f https://download.pytorch.org/whl/cu118/torch_stable.html else pip install torch==2.0.1+cpu torchvision==0.15.2+cpu fi

總結建議

方法 優點 缺點 適用情境
兩份 requirements.txt 簡單直接,技術門檻低 安裝時需手動選檔,不自動判斷GPU 小型專案或無專案管理工具時使用
pyproject.toml + Poetry 可設定依賴群組,條件化安裝,方便版本鎖定 設定稍複雜,安裝需明確指定群組 現代複雜專案,自動化和版本控管需求
pyproject.toml + uv 支援根據平臺條件切換索引與版本,自動化較好 仍在成長中,設定較新,需習慣工具 跨平台、高度自動化需求
安裝腳本判定與安裝 靈活,具體判斷GPU存在與否 需要額外腳本管理,不納入依賴管理工具 需要最大彈性或混合環境使用情境

補充說明

  • CPU 與 GPU 版本 PyTorch 通常是不同的 wheel 套件,需要從不同索引源(如 PyTorch 官方 CPU 或 CUDA wheel 源)安裝。這使得在同一依賴定義檔內自動判斷更不容易實作。

  • pyproject.toml 目前屬於靜態依賴定義,對於跨硬體需求仍依賴工具的擴展(Poetry群組、uv索引條件)或外部判斷腳本配合。

Method 1: pip install -e .

如果沒有 pyproject.toml 或是 setupy.py, 必須先產生一個。 此處以 setup.py 爲例。

1
2
3
4
5
6
7
8
9
10
from setuptools import setup, find_packages

setup(
    name='minbpe',
    version='0.1',
    packages=['minbpe'],  # Explicitly specify the package
    install_requires=[
        # List any dependencies here
    ],
)

接下來就執行下式,產生 minbpe 0.1 version.

1
$ pip install -e .

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from minbpe import BasicTokenizer, RegexTokenizer, GPT4Tokenizer

def test_encode_decode_identity(tokenizer, text):
    text = unpack(text)
    #tokenizer = tokenizer_factory()
    ids = tokenizer.encode(text)
    decoded = tokenizer.decode(ids)
    assert text == decoded

def unpack(text):
    # we do this because `pytest -v .` prints the arguments to console, and we don't
    # want to print the entire contents of the file, it creates a mess. So here we go.
    if text.startswith("FILE:"):
        dirname = os.path.dirname(os.path.abspath(__file__))
        taylorswift_file = os.path.join(dirname, text[5:])
        contents = open(taylorswift_file, "r", encoding="utf-8").read()
        return contents
    else:
        return text

tokenizer = GPT4Tokenizer()

test_strings = [
    "", # empty string
    "?", # single character
    "hello world!!!? (안녕하세요!) lol123 😉", # fun small string
    "FILE:taylorswift.txt", # FILE: is handled as a special string in unpack()
]

for text in test_strings:
    test_encode_decode_identity(tokenizer, text)



Appendix A uv sync --locked vs --frozen 的關鍵差異

--locked

“The project is re-locked before syncing unless the –locked or –frozen flag is provided”

  • 檢查 lockfile 是否最新:確保 uv.lockpyproject.toml 同步
  • 如果過期會失敗:如果 lockfile 過期,命令會報錯退出
  • 適用場景:CI/CD 環境,確保依賴完全一致
1
1
uv sync --locked  # 要求 uv.lock 必須是最新的,否則失敗

--frozen

“To use the lockfile without checking if it is up-to-date, use the –frozen option”

  • 不檢查 lockfile 狀態:直接使用現有的 uv.lock,不管是否過期
  • 不會重新鎖定:完全按照現有 lockfile 安裝
  • 適用場景:Docker 建構、生產部署
1
1
uv sync --frozen   # 直接使用 uv.lock,不檢查是否最新

實際使用建議

開發階段

1
uv sync           # 允許更新依賴

CI/CD 測試

1
uv sync --locked  # 確保環境一致性,lockfile 過期會報錯

生產部署 / Docker

1
uv sync --frozen  # 快速安裝,不檢查 lockfile 狀態

克隆別人的專案

1
uv sync --frozen  # 完全按照 lockfile 重現環境

重要注意事項

“This doesn’t work due to: error: the argument ‘–frozen’ cannot be used with ‘–locked’”

--locked--frozen 不能同時使用,它們是互斥的選項。

總結:--locked 是「嚴格模式」(必須最新),--frozen 是「信任模式」(直接使用現有)。

Appendix B - Activate-prj.sh

The activate-prj.sh script is a smart environment activation tool for Python projects using PyTorch that automatically detects the platform and hardware capabilities, sets up the appropriate virtual environment, and installs the correct PyTorch backend suited for the environment. Here is a detailed flow and purpose summary:

Purpose

  • Automates detection of platform capabilities (Windows WSL2, Linux, macOS) and CUDA GPU availability.
  • Sets up Python virtual environments tailored to the detected hardware (CUDA GPU or CPU).
  • Ensures correct PyTorch backend (CPU or CUDA) is installed by setting the PyTorch package index in advance.
  • Provides consistency and predictability for environment names and backend separation.

Flow Breakdown

  1. Project Detection:
    • Extracts the current project name (e.g., “my-rag-chatbot”).
    • Defines CUDA-specific environment name by appending -cuda.
  2. Platform & CUDA Detection:
    • If nvidia-smi tool exists and OS is Linux GNU, it detects a WSL2/Linux environment with NVIDIA GPU and enables CUDA environment.
    • Otherwise, if on macOS, it defaults to a CPU environment.
    • For other platforms (e.g., cloud servers), uses a CPU environment.
  3. Environment Path & PyTorch Index Selection:
Platform Env Path PyTorch Index Use Case
WSL2 + NVIDIA ~/.venvs/project-cuda https://download.pytorch.org/whl/cu121 GPU acceleration
macOS ~/.venvs/project cpu Apple Silicon/Intel CPUs
Other Linux ~/.venvs/project cpu Cloud or server CPU usage
  1. Virtual Environment Management:
    • If environment does not exist, create it via python3 -m venv.
    • Activate the environment using standard source .../bin/activate.
  2. Dependency Installation:
    • Sets UV_EXTRA_INDEX_URL environment variable to PyTorch index URL for installing the right backend.
    • Uses uv sync --active to install dependencies based on pyproject.toml.

Key Benefits

  • Automatic Platform Detection: No manual settings; works transparently across WSL2, macOS, Linux.
  • Chicken-and-Egg Problem Solved: Detects environment before PyTorch install, ensuring correct version and backend.
  • Environment Consistency: Predictable naming separating CUDA and CPU environments so projects remain clean and consistent.

Usage Pattern For New Projects

  1. Copy activate-prj.sh into project root and make executable.
  2. Declare PyTorch-dependent packages in pyproject.toml.
  3. Run the script (./activate-prj.sh) to set up and activate environment with dependencies ready.

Adaptations

  • Remove PyTorch index export for non-PyTorch projects.
  • Adjust CUDA version suffix in environment and PyTorch index URLs if using different CUDA.
  • Customize environment paths if needed.

Example Output When Run

1
2
3
4
5
🔥 CUDA environment detected, using CUDA PyTorch
🔄 Syncing dependencies with uv...
📦 PyTorch index: https://download.pytorch.org/whl/cu121
✅ Activated environment: my-project-cuda
🚀 Ready to run: ./run.sh

Reference