別再用 sys.path.insert 了——用 uv + hatchling 讓共用模組變正式套件

如果你的共用模組需要被多個子專案 import,讓它成為正式安裝的套件,而不是靠 sys.path hack。uv + hatchling 的 editable 模式讓這件事幾乎零成本。

你可能寫過這種 code

多個子專案要共用一組工具模組,於是在每個進入點加上:

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))

from common.utils import some_helper
Code language: JavaScript (javascript)

runtime 能跑,但問題不少:

  • IDE 紅線滿天飛——Pylance 不認 sys.path 動態修改,import 全部標紅
  • 路徑脆弱——搬個檔案就爆,.parent.parent 數量要人工對齊
  • 越寫越亂——有人寫 if __package__: / else: 雙分支來同時支援模組和腳本模式,可讀性直接砍半

更好的做法:讓它變成正式套件

核心思路很簡單——在 pyproject.toml 加 build-system,讓 uv sync 以 editable 模式安裝你的共用模組。之後所有 import 都是標準套件路徑,IDE 和 runtime 都認。

1. 把共用模組搬到根目錄

# Before                    # After
project/                    project/
├── agents/                 ├── agent_common/    ← 搬出來
│   ├── common/             │   ├── __init__.py
│   │   ├── __init__.py     │   ├── tracker.py
│   │   └── tracker.py      │   └── helpers.py
│   ├── project_a/          ├── agents/
│   │   └── agent.py        │   ├── project_a/
│   └── project_b/          │   │   └── agent.py
│       └── agent.py        │   └── project_b/
└── pyproject.toml          │       └── agent.py
                            └── pyproject.toml
Code language: PHP (php)

2. pyproject.toml 加兩個區塊

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["agent_common"]
Code language: JavaScript (javascript)

packages 要明確指定,因為 hatchling 預設找跟專案名稱對應的目錄。如果你的套件目錄名跟 [project] name 不一致,就需要這行。

3. uv sync

uv sync

hatchling 會以 editable 模式安裝,agent_common 變成正式可 import 的套件。

4. 把所有 hack 換成乾淨的 import

# Before
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
from common.tracker import SubagentTracker

# After
from agent_common.tracker import SubagentTracker
Code language: CSS (css)

刪掉 import sys、刪掉 sys.path.insert、刪掉 if __package__: 分支。

就這樣

整個過程只動了三個東西:

  1. mv 搬目錄
  2. pyproject.toml 加 6 行設定
  3. 每個檔案把 from common. 改成 from agent_common.

之後 IDE 不再報錯、import 路徑穩定、新人看 code 不用猜 sys.path 在幹嘛。

如果你的共用模組需要被多個子專案 import,讓它成為正式安裝的套件,而不是靠 sys.path hack。uv + hatchling 的 editable 模式讓這件事幾乎零成本。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *