- Khi chuyển sang uv, tốc độ cài đặt dependency Python nhanh hơn khoảng 10 lần so với pip, và có thể chạy bằng người dùng không phải root mà không cần venv riêng
- Dựa trên pyproject.toml, chỉ cần khai báo các dependency cấp cao nhất thì uv sẽ tự động quản lý file lock, đồng thời quản lý cây phụ thuộc và phiên bản chính xác tốt hơn
pip freeze
- Trong Dockerfile, cần thay đổi theo từng bước như sao chép binary uv và uvx, sử dụng file pyproject.toml/uv.lock, thiết lập biến môi trường
- Với các lệnh như uv sync/add/remove, uv:outdated, có thể dễ dàng thêm·xóa·cập nhật dependency và kiểm tra phiên bản mới nhất của package
- Có thể quản lý file lock và cập nhật dependency định kỳ, giúp đảm bảo tính nhất quán trong môi trường cộng tác và triển khai
Cài đặt dependency nhanh hơn 10 lần, không dùng venv, cấu hình môi trường không phải root
- uv là công cụ cải thiện đáng kể tốc độ cài đặt dependency cho các dự án Python so với pip truyền thống
- Với việc áp dụng uv, ở nhiều dự án như Flask/Django có thể đạt tốc độ cài đặt nhanh hơn khoảng 10 lần so với pip trước đây
- Ngay cả khi không dùng môi trường ảo (venv) riêng, vẫn có thể chạy an toàn bằng người dùng không phải root trong container
pyproject.toml vs requirements.txt
- Thay vì requirements.txt truyền thống, chỉ cần khai báo các dependency cấp cao nhất trong file pyproject.toml thì uv sẽ tự động tạo file
uv.lock
- Thêm mục
[project] dependencies vào pyproject.toml
- Xóa requirements.txt cũ
- File lock của uv tương tự kết quả
pip freeze, nhưng có cây phụ thuộc và thông tin phiên bản chính xác hơn
Thay đổi cấu hình Dockerfile
- Sao chép binary uv và uvx vào container để sử dụng (dùng binary Rust biên dịch tĩnh)
- Thay cho requirements*.txt cũ bằng cách sao chép các file pyproject.toml, uv.lock*
- Thêm biến môi trường:
UV_COMPILE_BYTECODE=1: biên dịch trước sang bytecode ở giai đoạn build
UV_PROJECT_ENVIRONMENT="/home/python/.local": cài package vào một đường dẫn cụ thể mà không tạo venv riêng
- Lệnh cài dependency cũng được đổi từ
pip3-install sang uv-install
- Ví dụ:
RUN chmod 0755 bin/* && bin/uv-install
Quản lý thêm, xóa, cập nhật dependency
- Có thể chạy lệnh uv trong container thông qua script run riêng
./run deps:install: cài đặt sau khi build image và đồng thời xuất file lock ra máy host
./run deps:install --no-build: chỉ cập nhật file lock mà không build
./run uv add mypackage --no-sync: chỉ cập nhật pyproject.toml và file lock, việc cài đặt thực tế sẽ chạy riêng
./run uv remove mypackage --no-sync: xóa package
./run uv:outdated: kiểm tra phiên bản mới nhất của các dependency hiện tại
Cung cấp video và hướng dẫn thực hành
- Cung cấp demo thực tế và ví dụ git diff cho việc áp dụng uv, viết pyproject.toml, thay đổi Dockerfile, lệnh lock/sync, thêm/xóa dependency, kiểm tra phiên bản mới nhất
- Cũng có thể tham khảo diff migration của hai dự án Flask và Django
2 bình luận
Đúng lúc tôi cũng đang định migrate thứ vốn được deploy bằng poetry, trông có vẻ ổn định và đơn giản nhỉ ^^
Ý kiến Hacker News
Cần lưu ý rằng uv hỗ trợ một quy trình làm việc thay thế trực tiếp cho pyenv, virtualenv và pip. Nó không bị ép buộc phải dùng lockfile hay
pyproject.toml. Có thể dùng lệnhuv python pin <version>để tạo file.python-versiontrong thư mục hiện tại,uv virtualenvđể tải về phiên bản Python đó như pyenv rồi tạo môi trường ảo.venv,uv pip install -r requirements.txtđể cài các gói trongrequirements.txt, vàuv run <command>để chạy lệnh kèm cả biến môi trường từ file.env. Tuy vậy, cần chú ý vấn đề thứ tự ưu tiên biến môi trường (issue liên quan)uv piplại chậm, chưa rõ nguyên nhân, có lẽ là do môi trường mạng của công typyproject.toml, nên thắc mắc là file.python-versioncó thực sự cần thiết khôngCách này làm mất đi ý nghĩa tồn tại của lock file. Nếu file không có hoặc không hợp lệ, tức là lock file đang có vấn đề nghiêm trọng và tốt hơn là người quen thuộc với dự án đó nên trực tiếp xử lý. Nếu không thì chẳng có lý do gì để giữ lock file cả. CI có thể tự động thay lock file và gây nhầm lẫn
uv locksẽ thất bại với thông báo thân thiện, vàerrexitcủa shell script sẽ dừng ngay. Việc redirect lỗi ởuv lock --checklà để tránh cùng một lỗi bị in ra hai lần. Nếu cố tình làm hỏng lock file rồi chạy script, build sẽ dừng kèm thông báo lỗi cụ thể. Tôi cũng đã sửa script thành if-else để rõ ràng hơn. Nếu không có lock file thì tạo mới là luồng xử lý đúng. Khi đó chỉ cần tạo rồi commituv sync --locked. Nếu lock file không có hoặc đã cũ thì nó sẽ fail rõ ràng. Tôi đề xuất luôn build cùng tùy chọn--locked--frozenthì lẽ ra lock file không được cập nhật, nhưng thực tế lại chạy ngược lại. Tôi đồng ý rằng nếu lock file không có hoặc không khớp thì cần có con người can thiệpTôi hoàn toàn phản đối việc công cụ Python lại được phát triển bằng ngôn ngữ không phải Python. C đã tồn tại và CPython đã được chuẩn hóa, nên không cần thiết phải có một ngôn ngữ mới nữa (ví dụ: Rust). Gói Pendulum đã chậm hỗ trợ 3.13 hơn 7 tháng, và tôi cho rằng là vì phần native viết bằng Rust nên thiếu người có thể sửa vấn đề đó. Nếu là C thì có lẽ tôi đã tự sửa rồi. (issue liên quan) Lý tưởng nhất là nếu muốn làm datetime nhanh bằng Rust hay ngôn ngữ ngoài khác thì nên làm theo dạng FFI để nhiều ngôn ngữ cùng dùng được. Cá nhân tôi vẫn chưa thực sự thích hướng đi dựa trên Rust, và giờ cũng phần nào hiểu vì sao cộng đồng Linux lại dè dặt với nó
Cần cẩn thận khi dùng uv thay cho pip. Mặc định nó không tạo file pyc, nên có thể khiến dịch vụ khởi động chậm hơn (tham khảo)
Khi dùng uv cho container Flask, không chỉ khác biệt về thời gian build lớn đến mức phát chán với pip, mà quá trình cài đặt cũng trở nên rất dễ dự đoán. Không còn cảnh khó chịu vì phiên bản dependency đổi ngoài ý muốn như với pip. Chỉ cần dùng
pyproject.toml, rồiuv locklà xong. Trong Docker, chỉ cần copy riêngpyproject.tomlvàuv.lock(HOT COPY) rồi chạyuv sync --frozen --no-install-project, có thể cache layer cài đặt mà bỏ qua mã ứng dụng. Ai từng khổ sở vì chỉ đổi một gói mà phải rebuild cả layer sẽ hiểu vì sao tính năng này quan trọng. Nếu dùng biến môi trườngUV_PROJECT_ENVIRONMENT=/home/python/.localthì có thể pre-warm base image mà không cần venv, từ đó chia sẻ build và giảm chi phí hạ tầng. Với tùy chọnUV_COMPILE_BYTECODE=1, file.pycsẽ được tạo khi build. Môi trường mutable bị loại bỏ và tính reproducibility được cưỡng chế; giờ nếu build hỏng thì có thể xác định rõ nguyên nhân là do lockfileĐến năm 2025 mà việc đóng gói và quản lý dependency của Python vẫn còn hỗn loạn
requirements.txtvàvenvlà đủTôi tò mò về mức độ bảo mật khi so sánh các trình quản lý gói Python như uv, pip, conda. Tốc độ thì tốt, nhưng tôi nghĩ bảo mật của package manager còn quan trọng hơn nhiều
Vì tôi là người đưa package lên PyPI, nên cá nhân vẫn muốn dùng uv vì tốc độ nhanh, nhưng nếu không có đảm bảo nó hoạt động hoàn toàn giống pip thì khó mà đổi ngay được. Nếu người dùng gặp lỗi với
pip install xxxthì tôi cũng phải tái hiện và debug trong đúng môi trường đóTôi nghĩ UV là một trong những thay đổi tích cực nhất gần đây trong hệ sinh thái đóng gói Python, kiểu chỉ cần chạy là thường cho ra kết quả ổn
Cũng có một bài hướng dẫn rất hay về việc dùng uv để dựng container production (xem hướng dẫn)