การจัดการ Python monorepo ด้วย UV Workspaces
(secondb.ai)สรุปการจัดการ Python monorepo ด้วย UV Workspaces
วิดีโอนี้แนะนำวิธีแก้ปัญหาที่เกิดขึ้นเมื่อจัดการแอปพลิเคชัน Python หลายตัวภายใน Git repository เดียว (monorepo) อย่างเป็นระเบียบด้วยฟีเจอร์ UV Workspaces
1. สรุปวิดีโอ
ปัญหา
เมื่อพัฒนาเครื่องมือ CLI และแอป FastAPI พร้อมกันใน repository เดียว จะเกิดปัญหาต่อไปนี้
- โค้ดซ้ำซ้อน: ฟังก์ชันที่ใช้ร่วมกันระหว่าง CLI และ API (เช่น ฟังก์ชัน crawl พาดหัวข่าว) ต้องคัดลอกและวางซ้ำ
- การจัดการสภาพแวดล้อมที่ซับซ้อน: แต่ละแอปต้องดูแล virtual environment แยกกัน ทำให้เวอร์ชัน dependency ชนกันหรือเปลืองพื้นที่ดิสก์
วิธีแก้: UV Workspaces
UV Workspaces มีฟีเจอร์หลัก 2 อย่างเพื่อแก้ปัญหาเหล่านี้
-
แชร์ dependency และใช้ virtual environment เดียว
- สามารถกำหนด dependency ที่ใช้ร่วมกันได้ในไฟล์
pyproject.tomlที่ root ของโปรเจ็กต์ - เมื่อรันคำสั่ง
uv syncแล้ว UV จะอ่านไฟล์ตั้งค่านี้และสร้าง virtual environment เดียว (.venv) ไว้ที่โฟลเดอร์ root เพื่อใช้ร่วมกันทั้ง repository - ทำให้ทุกโปรเจ็กต์ย่อย (CLI, API ฯลฯ) ใช้ environment และ dependency ชุดเดียวกัน ลดปัญหาเวอร์ชันชนกันและดูแลง่ายขึ้น
- สามารถกำหนด dependency ที่ใช้ร่วมกันได้ในไฟล์
-
แชร์โค้ดผ่าน internal package
- สามารถแยกโค้ดส่วนกลางที่ซ้ำกัน (เช่น ฟังก์ชัน
fetch_headlines) ออกเป็น "internal package" แยกต่างหาก เช่นcore - ผ่านการตั้งค่า workspace ระบบจะมองว่าแพ็กเกจ
coreนี้มาจาก local source แทนที่จะเป็น PyPI - จากนั้นทั้งแอป CLI และ API ก็สามารถ
importโค้ดที่ใช้ร่วมกันนี้กลับมาใช้ซ้ำได้ด้วยรูปแบบอย่างfrom core.news import fetch_headlines
- สามารถแยกโค้ดส่วนกลางที่ซ้ำกัน (เช่น ฟังก์ชัน
2. วิธีใช้งาน UV Workspaces
ขั้นตอนที่ 1: ตั้งค่า workspace
สร้างไฟล์ pyproject.toml ที่โฟลเดอร์ root ของโปรเจ็กต์ แล้วกำหนดส่วน [tool.uv.workspace] เพื่อบอกว่ามีโปรเจ็กต์ย่อยอยู่ที่ไหน
[tool.uv.workspace]
# รับรู้ทุกโฟลเดอร์ย่อยในโฟลเดอร์ "packages" เป็นสมาชิกของ workspace
members = ["packages/*"]
ขั้นตอนที่ 2: จัดการ dependency
- dependency ที่ใช้ร่วมกัน: dependency ที่ทุกโปรเจ็กต์ใช้ร่วมกัน (เช่น
python-dotenv) ให้เพิ่มไว้ใน rootpyproject.toml - dependency เฉพาะแอป: dependency ที่ใช้เฉพาะบางแอป (เช่น
fastapi,uvicornสำหรับapi) ให้เพิ่มไว้ในpyproject.tomlของแอปนั้น (เช่นpackages/api/pyproject.toml) - เมื่อรัน
uv syncจากโฟลเดอร์ root, UV จะสแกนpyproject.tomlทุกไฟล์และติดตั้ง dependency ที่จำเป็นทั้งหมดลงใน virtual environment ที่ root
ขั้นตอนที่ 3: แชร์โค้ดเป็น internal package
- สร้างแพ็กเกจใหม่ (โฟลเดอร์) สำหรับเก็บโค้ดที่ใช้ร่วมกัน เช่น
packages/core - เพิ่มแพ็กเกจนี้ใน root
pyproject.tomlเหมือนเป็น dependency ปกติ - เพิ่มส่วน
[tool.uv.sources]ใน rootpyproject.tomlเพื่อให้ระบบค้นหาแพ็กเกจcoreจากภายใน workspace แทน PyPI
[project]
# 1. เพิ่ม internal package เป็น dependency
dependencies = [
"core",
"python-dotenv"
]
# 2. ระบุว่า 'core' เป็นแพ็กเกจ local workspace
[tool.uv.sources]
core = { workspace = true }
- รัน
uv syncอีกครั้ง แล้วแพ็กเกจcoreจะถูกติดตั้งจาก local source - ตอนนี้ใน
packages/apiหรือpackages/cliก็สามารถเรียกใช้โค้ดส่วนกลางได้ด้วยคำสั่งfrom core.news import ...
ขั้นตอนที่ 4: รันโปรเจ็กต์
เมื่อต้องการรันโปรเจ็กต์ใดโปรเจ็กต์หนึ่ง ให้ใช้ uv run --from <ชื่อแพ็กเกจ>
# รัน API server
uv run --from packages/api uvicorn main:app --reload
# รันเครื่องมือ CLI
uv run --from packages/cli python main.py
3. เหมาะกับใคร
- เหมาะเมื่อจัดการสคริปต์ automation ขนาดเล็กหลายตัว, webhook, API, CLI ฯลฯ ภายใน repository เดียว
- มีประโยชน์มากเมื่อแอปเหล่านี้แชร์ logic หรือ dependency ร่วมกัน
- ในทางกลับกัน อาจไม่เหมาะกับสคริปต์เดี่ยว, แพ็กเกจที่จะเผยแพร่แยกบน PyPI อย่างอิสระ, หรือแอปที่ไม่เกี่ยวข้องกันเลย
ลิงก์วิดีโอต้นฉบับ: https://www.youtube.com/watch?v=N_ypJwV8Q8I
1 ความคิดเห็น
ดูคล้ายกับ pnpm มากเลยครับ