18 คะแนน โดย darjeeling 2025-11-09 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

สรุปการจัดการ 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 อย่างเพื่อแก้ปัญหาเหล่านี้

  1. แชร์ dependency และใช้ virtual environment เดียว

    • สามารถกำหนด dependency ที่ใช้ร่วมกันได้ในไฟล์ pyproject.toml ที่ root ของโปรเจ็กต์
    • เมื่อรันคำสั่ง uv sync แล้ว UV จะอ่านไฟล์ตั้งค่านี้และสร้าง virtual environment เดียว (.venv) ไว้ที่โฟลเดอร์ root เพื่อใช้ร่วมกันทั้ง repository
    • ทำให้ทุกโปรเจ็กต์ย่อย (CLI, API ฯลฯ) ใช้ environment และ dependency ชุดเดียวกัน ลดปัญหาเวอร์ชันชนกันและดูแลง่ายขึ้น
  2. แชร์โค้ดผ่าน 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) ให้เพิ่มไว้ใน root pyproject.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

  1. สร้างแพ็กเกจใหม่ (โฟลเดอร์) สำหรับเก็บโค้ดที่ใช้ร่วมกัน เช่น packages/core
  2. เพิ่มแพ็กเกจนี้ใน root pyproject.toml เหมือนเป็น dependency ปกติ
  3. เพิ่มส่วน [tool.uv.sources] ใน root pyproject.toml เพื่อให้ระบบค้นหาแพ็กเกจ core จากภายใน workspace แทน PyPI
<!-- end list -->
[project]  
# 1. เพิ่ม internal package เป็น dependency  
dependencies = [  
    "core",  
    "python-dotenv"  
]  
  
# 2. ระบุว่า 'core' เป็นแพ็กเกจ local workspace  
[tool.uv.sources]  
core = { workspace = true }  
  1. รัน uv sync อีกครั้ง แล้วแพ็กเกจ core จะถูกติดตั้งจาก local source
  2. ตอนนี้ใน 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 ความคิดเห็น

 
pcj9024 2025-11-10

ดูคล้ายกับ pnpm มากเลยครับ