Từ bỏ Pip và Poetry: Tại sao uv là công cụ Python duy nhất bạn cần

Programming tutorial - IT technology blog
Programming tutorial - IT technology blog

Chấm dứt nỗi ám ảnh về công cụ trong Python

Bất kỳ ai đã dành một tuần trong hệ sinh thái Python đều hiểu rõ sự khó chịu đặc thù khi quản lý dependency. Trong nhiều năm, chúng ta đã phải chắp vá các quy trình làm việc lại với nhau. Chúng ta dùng pip để cài đặt, venv để cô lập môi trường, pyenv để chuyển đổi phiên bản, và Poetry hoặc pip-tools để xử lý mớ hỗn độn thực sự của việc phân giải dependency.

Sự phân mảnh này thật mệt mỏi. Bạn rốt cuộc cần đến đóng bốn công cụ khác nhau chỉ để chạy được một chương trình ‘Hello World’ cơ bản. Tệ hơn nữa, pip nổi tiếng là chậm chạp, và việc chờ đợi Poetry khóa (lock) dependency đôi khi chẳng khác nào chờ sơn khô. Đây chính là lúc uv thay đổi cuộc chơi. Được xây dựng bởi đội ngũ tại Astral (những người đã tạo ra Ruff), uv là một công cụ duy nhất, hợp nhất được viết bằng Rust với mục tiêu thay thế toàn bộ stack công cụ Python hiện tại.

Chính xác thì uv là gì?

Về cơ bản, uv là một bộ cài đặt và phân giải package Python hiệu suất cao. Tuy nhiên, nếu chỉ gọi nó là một trình cài đặt thì đã bỏ qua tính đa năng của nó. Nó là một con dao Thụy Sĩ hoạt động như:

  • Trình quản lý package: Một sự thay thế trực tiếp cho pippip-compile.
  • Trình quản lý môi trường: Xử lý việc tạo virtualenv trong vài mili giây.
  • Trình quản lý phiên bản Python: Tải và quản lý các phiên bản Python, thay thế cho pyenv.
  • Trình quản lý dự án: Quản lý lockfile và dependency tương tự như Poetry.

Vì là một file thực thi (binary) Rust độc lập, uv không yêu cầu phải cài đặt Python trước đó để hoạt động. Điều này giải quyết bài toán “con gà và quả trứng” khi phải cài đặt một công cụ để quản lý chính công cụ đó. Về hiệu suất thuần túy, nó thường phân giải và cài đặt package nhanh hơn từ 10 đến 100 lần so với pip nhờ sử dụng cache toàn cục và cơ chế song song hóa mạnh mẽ.

Bắt đầu sử dụng

Bạn có thể cài đặt uv chỉ trong vài giây. Không giống như các trình quản lý khác yêu cầu cấu hình shell phức tạp, uv được phân phối dưới dạng một file binary gọn nhẹ chỉ 7MB.

# Trên macOS và Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Trên Windows
powershell -ExecutionPolicy ByPass -c "ir https://astral.sh/uv/install.ps1 | iex"

Kiểm tra cài đặt bằng cách chạy:

uv --version

Quản lý phiên bản Python không còn là rắc rối

Tôi từng dựa vào pyenv, nhưng nó thường gây cảm giác rắc rối với các shell hook và dependency khi build. uv xử lý việc này một cách tự nhiên bằng cách tải về các bản Python binary đã được build sẵn. Bạn có thể cài đặt các phiên bản cụ thể chỉ với một câu lệnh:

uv python install 3.11 3.12 3.13

Công cụ này rất thông minh. Nếu dự án của bạn yêu cầu Python 3.12, uv sẽ tự động tìm hoặc tải nó về cho bạn. Bạn không còn cần phải chuyển đổi phiên bản thủ công khi di chuyển giữa các repository; uv sẽ đọc file .python-version hoặc pyproject.toml và xử lý mọi công việc nặng nhọc.

Quy trình làm việc dự án tinh gọn

Hãy quên đi nghi thức cũ kỹ python -m venv .venv và việc liên tục phải chạy script source để kích hoạt môi trường. uv giới thiệu một quy trình làm việc hợp nhất mà tôi hiện đang áp dụng cho mọi dự án mới.

1. Khởi tạo dự án

mkdir my-new-app
cd my-new-app
uv init

Câu lệnh này tạo ra một file pyproject.toml và một file hello.py mẫu. Nó mang lại cảm giác quen thuộc cho bất kỳ ai đến từ hệ sinh thái Rust hoặc Node.js.

2. Thêm dependency

Việc thêm package diễn ra gần như tức thì. uv phân giải cây dependency và cập nhật file uv.lock trước khi bạn kịp nhấp một ngụm cà phê.

uv add fastapi uvicorn requests

Trong một dự án gần đây, việc chuyển đổi pipeline CI của chúng tôi từ pip install sang uv sync đã giảm thời gian build từ 4 phút xuống chỉ còn 28 giây. Tốc độ này không chỉ là một sự xa xỉ; nó thay đổi căn bản tần suất bạn sẵn lòng lặp lại (iterate) mã nguồn của mình.

3. Chạy mã nguồn

Việc kích hoạt môi trường thủ công giờ đây là tùy chọn. Bạn có thể thực thi các script trực tiếp trong môi trường đã được khóa của dự án bằng lệnh uv run:

uv run python hello.py
# Hoặc khởi chạy một web server
uv run uvicorn main:app --reload

Script di động với PEP 723

Một trong những tính năng nổi bật của uv là hỗ trợ PEP 723 (Inline Script Metadata). Bạn có thể viết một file Python duy nhất và định nghĩa các dependency của nó trực tiếp bên trong các comment. Điều này thật hoàn hảo để chia sẻ các script tiện ích mà không cần gửi kèm file requirements.txt riêng biệt.

# script.py
# /// script
# dependencies = ["requests", "rich"]
# ///

import requests
from rich import print

response = requests.get("https://api.github.com/zen")
print(f"[bold green]GitHub nói:[/bold green] {response.text}")

Chạy nó với lệnh uv run script.py. uv sẽ tạo một môi trường tạm thời ẩn, cài đặt hai package đó, thực thi mã và dọn dẹp sau khi xong. Nó giữ cho môi trường toàn cục của bạn luôn sạch sẽ.

Tối ưu hóa Docker Build

Việc Docker hóa các ứng dụng Python trước đây thường đi kèm với các layer cồng kềnh và việc cài đặt pip chậm chạp. uv tinh gọn quá trình này bằng cách cho phép bạn mount cache của nó hoặc sử dụng flag --frozen để đảm bảo môi trường production khớp chính xác với lockfile ở môi trường phát triển.

FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen

COPY . .
CMD ["uv", "run", "python", "main.py"]

Cách thiết lập này đảm bảo tính tái lập chính xác (bit-for-bit reproducibility) mà không tốn thêm chi phí tài nguyên từ các công cụ cũ.

Tại sao việc chuyển đổi là tất yếu

Cộng đồng Python đang chuyển hướng sang uv với tốc độ chóng mặt. Nó không chỉ đơn thuần là việc tăng tốc độ gấp 10 lần; đó là việc giảm bớt gánh nặng tâm trí khi phải nhớ công cụ nào quản lý phần nào trong quy trình làm việc. Bằng cách hợp nhất mọi thứ vào một file binary duy nhất, thiết lập của bạn trở nên dễ dự đoán và cực kỳ nhanh chóng.

Tôi đã gỡ bỏ hoàn toàn pyenvvirtualenv khỏi máy mình. Vì uv tuân thủ các tiêu chuẩn của pyproject.toml, việc di chuyển hầu như không gây đau đớn. Ngay cả khi bạn đang dùng Poetry hiện nay, uv vẫn có thể quản lý các dự án đó mà không yêu cầu bạn thay đổi bất kỳ dòng cấu hình nào.

Lời kết

Quản lý môi trường từng là phần tẻ nhạt nhất trong quá trình phát triển Python. uv biến sự khó chịu đó thành một tác vụ chạy ngầm mà bạn hiếm khi phải bận tâm. Đây chính là khoảnh khắc “Cargo” mà Python đã khao khát suốt một thập kỷ qua. Nếu bạn trân trọng thời gian của mình, hãy thử uv cho dự án tiếp theo. Bạn sẽ không muốn quay lại đâu.

Share: