18 điểm bởi darjeeling 2025-11-09 | 1 bình luận | Chia sẻ qua WhatsApp

Tóm tắt quản lý monorepo Python bằng UV Workspaces

Video này giới thiệu cách giải quyết gọn gàng các vấn đề phát sinh khi quản lý nhiều ứng dụng Python trong một kho Git duy nhất (monorepo) bằng tính năng UV Workspaces.

1. Tóm tắt video

Vấn đề

Khi đồng thời phát triển một công cụ CLI và một ứng dụng FastAPI trong cùng một repository, sẽ phát sinh các vấn đề sau.

  • Trùng lặp mã nguồn: Các chức năng dùng chung giữa CLI và API (ví dụ: hàm crawl tiêu đề) phải được sao chép/dán lại.
  • Quản lý môi trường phức tạp: Mỗi ứng dụng cần quản lý một môi trường ảo riêng, dễ gây xung đột phiên bản phụ thuộc hoặc lãng phí dung lượng đĩa.

Giải pháp: UV Workspaces

UV Workspaces cung cấp hai tính năng cốt lõi để giải quyết các vấn đề này.

  1. Phụ thuộc dùng chung và một môi trường ảo duy nhất

    • Có thể định nghĩa các phụ thuộc dùng chung trong tệp pyproject.toml ở gốc dự án (cấp cao nhất).
    • Khi chạy lệnh uv sync, UV sẽ đọc tệp cấu hình này và tạo một môi trường ảo duy nhất (.venv) trong thư mục gốc để dùng chung cho toàn bộ repository.
    • Nhờ đó, mọi dự án con (CLI, API, v.v.) sẽ chia sẻ cùng một môi trường và các phụ thuộc giống nhau, giúp tránh xung đột phiên bản và đơn giản hóa việc quản lý.
  2. Chia sẻ mã nguồn qua gói nội bộ

    • Có thể tách phần mã dùng chung bị trùng lặp (ví dụ: hàm fetch_headlines) thành một "gói nội bộ" riêng như core.
    • Thông qua cấu hình workspace, gói core này sẽ được nhận diện là nguồn cục bộ thay vì từ PyPI.
    • Từ đó, ứng dụng CLI và API có thể tái sử dụng mã chung này bằng cách import, chẳng hạn from core.news import fetch_headlines.

2. Cách sử dụng UV Workspaces

Bước 1: Cấu hình workspace

Tạo tệp pyproject.toml trong thư mục gốc của dự án, rồi định nghĩa phần [tool.uv.workspace] để chỉ ra vị trí của các dự án con.

[tool.uv.workspace]  
# Nhận diện mọi thư mục con trong thư mục "packages" là thành viên workspace  
members = ["packages/*"]  

Bước 2: Quản lý phụ thuộc

  • Phụ thuộc dùng chung: Các phụ thuộc được tất cả dự án cùng sử dụng (ví dụ: python-dotenv) nên được thêm vào pyproject.toml ở gốc.
  • Phụ thuộc riêng: Các phụ thuộc chỉ dùng cho một ứng dụng cụ thể (ví dụ: fastapi, uvicorn chỉ cho api) nên được thêm vào pyproject.toml của ứng dụng đó (ví dụ: packages/api/pyproject.toml).
  • Khi chạy uv sync ở thư mục gốc, UV sẽ quét mọi pyproject.toml và cài toàn bộ phụ thuộc cần thiết vào môi trường ảo ở gốc.

Bước 3: Chia sẻ mã bằng gói nội bộ

  1. Tạo một gói (thư mục) mới chứa mã dùng chung, ví dụ packages/core.
  2. Thêm gói này vào pyproject.toml ở gốc như một phụ thuộc thông thường.
  3. Thêm phần [tool.uv.sources] vào pyproject.toml ở gốc để cấu hình cho UV tìm gói core bên trong workspace thay vì trên PyPI.
<!-- end list -->
[project]  
# 1. Thêm gói nội bộ làm phụ thuộc  
dependencies = [  
    "core",  
    "python-dotenv"  
]  
  
# 2. Khai báo 'core' là gói cục bộ trong workspace  
[tool.uv.sources]  
core = { workspace = true }  
  1. Chạy lại uv sync, khi đó gói core sẽ được cài từ nguồn cục bộ.
  2. Giờ đây, trong packages/api hoặc packages/cli, bạn có thể dùng cú pháp from core.news import ... để gọi mã dùng chung.

Bước 4: Chạy dự án

Khi chạy một dự án cụ thể, hãy dùng uv run --from <tên_gói>.

# Chạy máy chủ API  
uv run --from packages/api uvicorn main:app --reload  
  
# Chạy công cụ CLI  
uv run --from packages/cli python main.py  

3. Đối tượng nên dùng

  • Phù hợp khi quản lý nhiều script tự động hóa nhỏ, webhook, API, CLI, v.v. trong cùng một repository.
  • Đặc biệt hữu ích khi các ứng dụng này cùng chia sẻ logic hoặc phụ thuộc chung.
  • Ngược lại, có thể không phù hợp để quản lý một script đơn lẻ, một gói sẽ được phát hành độc lập lên PyPI, hoặc các ứng dụng hoàn toàn không liên quan đến nhau.

Liên kết video gốc: https://www.youtube.com/watch?v=N_ypJwV8Q8I

1 bình luận

 
pcj9024 2025-11-10

Khá giống với pnpm.