- Khi dùng uv, việc quản lý phụ thuộc được tự động hóa khi chạy script Python
- Không cần quản lý môi trường ảo riêng, môi trường cho từng script sẽ được tự động tạo và duy trì
- Có thể khai báo các gói cần thiết bằng nhiều cách như inline metadata hoặc tùy chọn dòng lệnh
- Việc quản lý gói và phiên bản Python cũng có thể được khai báo theo từng script và tự động điều chỉnh
- Có thể tăng tính tái lập và khả năng bảo trì bằng file lock cùng các tùy chọn giới hạn phiên bản phụ thuộc
Tổng quan
- uv là công cụ tự động quản lý các phụ thuộc gói mà một script Python cần khi chạy script đó
- Người dùng không cần tự thực hiện các bước phiền phức như tạo môi trường ảo hay cài đặt gói
- Công cụ cung cấp nhiều tùy chọn chạy, cách dùng inline metadata, nhiều phương thức khai báo phụ thuộc và các tính năng kiểm soát khác nhau
Môi trường Python và vai trò của uv
- Python có môi trường riêng biệt cho từng lần cài đặt
- Thông thường, việc tạo và quản lý môi trường ảo là điều được khuyến nghị
- uv tự động quản lý môi trường ảo và xử lý phụ thuộc theo cách khai báo
- Với script đơn giản, có thể chạy ngay bằng
uv run example.py
- Nếu chỉ dùng thư viện chuẩn thì sẽ hoạt động mà không cần cấu hình thêm
Truyền tham số và cách nhập dữ liệu
- Có thể truyền tham số dòng lệnh cho script
- Cũng hỗ trợ nhận trực tiếp mã script từ đầu vào chuẩn hoặc dùng tính năng here-document
Môi trường dự án và tùy chọn --no-project
- Nếu script được chạy trong thư mục dự án (ví dụ nơi có
pyproject.toml), các phụ thuộc của dự án cũng sẽ được cài đặt
- Nếu không cần, có thể đặt cờ
--no-project trước tên script để bỏ qua môi trường dự án
Khai báo và quản lý phụ thuộc của script
- Nếu cần gói bên ngoài, có thể chạy script bằng cách chỉ định phụ thuộc với tùy chọn dòng lệnh
--with
- Cũng hỗ trợ ràng buộc phiên bản cụ thể, và có thể chỉ định nhiều phụ thuộc bằng cách lặp lại tùy chọn này
- Có thể thêm phụ thuộc bổ sung trong môi trường dự án, và nếu không muốn thì có thể kiểm soát bằng
--no-project
Inline Script Metadata (chuẩn PEP 723)
- Python hiện hỗ trợ định dạng chuẩn để khai báo phụ thuộc hoặc phiên bản Python ngay trong chính script
- Có thể dễ dàng tạo script chứa inline metadata bằng
uv init --script
- Có thể thêm và quản lý các phụ thuộc cần thiết cho script ở định dạng TOML bằng
uv add --script
- Nếu có inline metadata, phụ thuộc của dự án sẽ bị bỏ qua và chỉ áp dụng phụ thuộc của script
Khai báo và quản lý phiên bản Python
- Có thể chỉ định phiên bản Python mong muốn trong script hoặc tại thời điểm chạy
- Nếu phiên bản được chỉ định chưa có, nó sẽ tự động được tải xuống và thiết lập
Viết script có thể chạy trực tiếp bằng shebang
- Có thể dùng shebang (
#!...) để tạo tệp thực thi trực tiếp theo cách uv run --script
- Khi đó, việc khai báo phụ thuộc và phiên bản Python cũng có thể đặt ở đầu script
Hỗ trợ chỉ mục gói và xác thực
- Có thể dùng chỉ mục gói tùy chỉnh với tùy chọn
--index
- Thông tin index cũng được đưa vào metadata
- Nếu cần xác thực, có thể tham khảo tài liệu riêng
Khóa phụ thuộc (Lock) và tăng khả năng tái lập
- Có thể tạo và quản lý file lock ở cấp độ script bằng
uv lock --script
- Sau đó khi chạy hoặc thêm phụ thuộc, file lock sẽ được tái sử dụng và cập nhật khi cần
- Có cung cấp tùy chọn
exclude-newer để đảm bảo khả năng tái lập phiên bản bằng cách loại trừ các bản phát hành sau một ngày cụ thể
- Ngày được chỉ định bằng dấu thời gian RFC 3339
Tính linh hoạt của phiên bản Python
- Ở mỗi lần chạy, có thể chỉ định dùng bất kỳ phiên bản Python nào bằng tùy chọn dòng lệnh
- Ví dụ:
uv run --python 3.10 example.py
Hỗ trợ Windows
- Các script có phần mở rộng
.pyw sẽ được chạy bằng pythonw trên Windows
- Các script giao diện GUI cũng có thể chạy cùng với phụ thuộc
Tài liệu tham khảo
- Có thể tham khảo tài liệu CLI và hướng dẫn chạy/cài đặt công cụ để biết cách dùng lệnh chi tiết hơn
Kết luận
- uv là công cụ giúp tự động và đơn giản hóa việc quản lý môi trường chạy, phụ thuộc, phiên bản, chỉ mục gói và khả năng tái lập của script Python, từ đó đồng thời nâng cao năng suất và độ tin cậy
7 bình luận
Tôi cũng đã chuyển từ pip sang uv, và đúng là chỉ riêng tốc độ cực nhanh thôi cũng đã đủ đáng để chuyển rồi.
Bài này xuất hiện khá thường xuyên nên hôm qua tôi mới thử dùng lần đầu.. thật sự rất nhanh. Trời ơi..
Có vẻ tôi đã thấy hơn 5 bài viết liên quan đến uv ở đây rồi;;;
Bỏ qua các tính năng khác, chỉ riêng tốc độ thôi cũng đã là lý do đủ để dùng.
Nếu bảo quay lại dùng pip thì gần như là tôi không thể chịu nổi nữa.
Tôi đang thay phần quản lý gói hệ thống của conda bằng
flake.nix, và ngoài các dự án cộng tác hoặc những dự án hiện có vốn được bảo trì bằng conda+pip, về mặt cá nhân có lẽ từ nay tôi sẽ dùng uv+nix.Uv - công cụ đóng gói Python siêu nhanh được viết bằng Rust
Cách đổi mới quy trình làm việc phát triển Python với UV
Sử dụng script Python với uv và PEP 723
Trải nghiệm sử dụng uv trong 1 năm: ưu, nhược điểm và những điều cần cân nhắc khi migration
Gần đây tôi đã thay thế hầu hết việc chạy Python bằng uv, và nó thực sự rất nhanh.
Dù có một vài tính năng nâng cao chưa tương thích hoàn toàn, nhưng trong đa số trường hợp nó hoạt động gần như giống hệt.
Ý kiến trên Hacker News
Đã trải nghiệm và thấy tính năng "khai báo phụ thuộc cho script" thực sự rất hữu ích
Như được giới thiệu trong tài liệu hướng dẫn chính thức, có thể khai báo các phụ thuộc bằng chú thích ở đầu mã Python như sau
Lưu tệp này thành script.py rồi chạy bằng
uv run script.py, các phụ thuộc đã khai báo sẽ được cài vào một môi trường ảo tạm thời như có phép màu và có thể chạy ngay lập tứcĐây là một triển khai của PEP 723 trong Python, và Claude 4 cũng biết mẹo này, nên nếu prompt kiểu “hãy viết một script Python có phụ thuộc inline” thì nó sẽ tạo đúng
Ví dụ có thể yêu cầu viết mã dùng httpx và click để tải xuống tệp lớn và hiển thị thanh tiến trình
Trước thời Claude 4, để làm kiểu này cần một dự án tùy chỉnh và hướng dẫn riêng, nhưng giờ thì không còn như vậy nữa
Cũng có thể tham khảo các trường hợp sử dụng chi tiết
Cũng cảm thấy chế độ shebang thực sự rất hữu ích
Nếu thêm shebang ở dòng đầu của script như dưới đây thì có thể chạy kiểu
./script.shMong là nó có thể dùng cùng định dạng với file requirements
Nếu vậy thì với người dùng không có uv, cũng có thể cung cấp một chú thích đơn giản kèm one-liner để cài tương tự bằng pip
Chẳng hạn có vẻ có thể tiếp cận theo kiểu
pip install -r <(head myscript.py)Thực tế thì PEP723 hiện không chỉ được uv, vốn đang rất được chú ý gần đây, hỗ trợ mà còn được pipx và hatch hỗ trợ
Ngoài ra pip-tools v.v. cũng đã có trong roadmap hỗ trợ
(xem issue liên quan)
Lần đầu nhìn thấy, đã từng tưởng bên cạnh requests là emoji trái tim
Tôi nghĩ cách này thực sự rất hay
Nhưng mong rằng một ngày nào đó nó sẽ được đưa vào cú pháp ngôn ngữ tích hợp sẵn thay vì là magic comment
Comment trông hơi lộn xộn
Tất nhiên tôi cũng hiểu rằng với góc nhìn công cụ thì magic comment dễ parse hơn, và còn có những cân nhắc mang tính cấu trúc như Python core không có nhiều kiến thức về packaging, nhưng vẫn hy vọng một ngày nào đó sẽ có cú pháp tích hợp sẵn
Tôi đồng cảm với cách làm này
Python không bắt buộc phải có file requirements.txt, nhưng thật đáng tiếc là nếu quản lý lỏng lẻo thì thường xuyên phát sinh sự bất tiện khi chức năng bị hỏng
Xem tweet liên quan
Muốn chia sẻ một cái bẫy tôi gặp phải với cách này
Tôi đã dùng nó cho một script khởi động lại router khi mất Internet, nhưng vì thao tác cài phụ thuộc phụ thuộc vào kết nối Internet nên khi mạng không hoạt động, bản thân script cũng không thể chạy
Tôi đã phát hiện sớm và giải quyết bằng cách cài sẵn phụ thuộc, nhưng khuyên mọi người đừng mắc sai lầm như tôi và đừng dùng nó trong môi trường airgapped thực sự (môi trường bị cô lập mạng hoàn toàn)
Ngay cả khi có cache của uv, vẫn có thể bị cache miss
Khi dùng tùy chọn
uv run --offline, có thể tận dụng các phụ thuộc đã được cache để chạy mà không cần kiểm tra phiên bản mớiTính năng tương tự cũng hoạt động với
uvx(uvx --offline ...)Tôi hiểu là nếu có dùng phụ thuộc hoặc venv thì ít nhất phải chạy một lần khi có Internet, rồi sau đó mới có thể dùng offline
Gần đây tôi có cảm giác nhiều tính năng trong hệ sinh thái Python đang ngày càng ăn khớp với nhau tốt hơn
Với sự kết hợp của Marimo và phụ thuộc script của uv, tôi bắt đầu tạo các công cụ báo cáo/chẩn đoán có tính tái lập, phù hợp để các nhóm khác sử dụng
Đây là tính năng tôi thích nhất của uv, đến mức vì nó mà tôi chuyển sang dùng uv
Nhiều script git-hooks có phụ thuộc riêng, và tôi không muốn cài chúng vào venv chính
Chỉ cần thêm một dòng
#!/usr/bin/env -S uv run --script --python 3.13, rồi với dev chỉ cần hướng dẫnbrew install uv, và có thể dùng trực tiếp trong script mà không cần tạo venv riêngCó ai biết vì sao cần cờ
-SkhôngTrên môi trường BSD của tôi, cả
/usr/bin/env -S uv run --python 3.11 pythonvà/usr/bin/env uv run --python 3.11 pythonđều chạy Python shell nên tôi cảm thấy kết quả như nhauTôi cũng không diễn giải rõ được từ trang manual của env, nên nếu ai có thông tin hữu ích thì rất muốn nghe
(
-Sở đây có vai trò tách đối số theo khoảng trắng)Nhờ UV mà kế hoạch ban đầu chuyển một đợt migrate Python quy mô lớn sang golang của chúng tôi đã có thể thu hẹp lại
Đặc biệt là các tác vụ dạng script nhỏ thì không còn cần phải chuyển nữa
Tôi thực sự tin đây là một tính năng ‘killer’
Nếu trong phụ thuộc có Pytorch thì cách này có thể hơi bị hạn chế
Uv cung cấp hỗ trợ tích hợp khá tốt cho Pytorch, nhưng chỉ với header của script thì hơi tiếc là không có cách rõ ràng để chọn wheel index phù hợp nhất (CPU, CUDA, ROCm, v.v.)
Mong là VS Code có thể dễ dàng nhận diện venv do uv tự động tạo ra
Hiện tại Python extension đang gạch đỏ toàn bộ import từ bên thứ ba
Giải pháp tạm thời là tìm thủ công đường dẫn venv trong thư mục Cache của uv rồi đăng ký, nhưng nếu venv thường xuyên bị tạo lại thì lại phải lặp lại, khá phiền
uv python find --script "${filePath}"Tôi đang phát triển một extension để VS Code tự động phát hiện và kích hoạt tính năng đó
Tôi cực kỳ thích tính năng này của UV
Ngay cả jupyter notebook cũng có thể chạy bằng one-liner như sau mà không cần cài riêng
Mọi thứ được cài vào môi trường ảo tạm thời, rồi sau đó được dọn dẹp sạch sẽ
Nếu chạy trong một dự án thì nó cũng tự động nhận diện các phụ thuộc của dự án đó
Tuy vậy, cũng không hẳn là được dọn dẹp ‘sạch hoàn toàn’, vì thư mục cache của uv có thể tiếp tục phình to
Tôi cũng thường xuyên dùng theo kiểu
uv run --with ipython --with boto3 ipython, và nó thực sự giúp tiết kiệm rất nhiều thời gianGần đây tôi phát hiện một vấn đề nhỏ liên quan đến
uv runNếu chạy script từ bên ngoài thư mục dự án, nó sẽ tìm
pyproject.tomltrong thư mục làm việc hiện tại thay vì vị trí thực của tệp scriptVì vậy script lưu phụ thuộc trong
pyproject.tomlcó thể không hoạt động đúng nếu chạy từ bên ngoài theo kiểuuv run path/to/my/script.pyHiện tượng này có thể giải quyết bằng cách luôn dùng phụ thuộc inline hoặc dùng tham số
--project, nhưng như vậy phải nhập đường dẫn script hai lần nên khá bất tiệnBản thân uv thì rất tuyệt, nhưng đặc điểm nhỏ này lại gây khó chịu đáng kể
Tôi đã dùng khá hài lòng cách shebang dành riêng cho uv và phụ thuộc trong script
Thêm vào đó, việc có thể tạo cả file lock dành riêng cho một script duy nhất bằng lệnh
uv lock --script example.pylại càng gây ấn tượngPython packaging đã kéo dài hơn 20 năm mà giờ trải nghiệm tự nhiên như thế này mới xuất hiện, thật đáng ngạc nhiên
Trong tổ chức của chúng tôi, chúng tôi còn dùng phụ thuộc trong lockfile để quét bằng
trivy fs uv.lock, nhằm ngăn việc chạy mã có CVE đã biết