14 điểm bởi GN⁺ 2025-06-25 | 2 bình luận | Chia sẻ qua WhatsApp
  • Trình quản lý gói uvPEP 723 giúp có thể chạy script Python mà không gặp vấn đề về phụ thuộc
  • Tính năng uvx tự động tạo môi trường ảo dùng tạm, giải quyết sự bất tiện trong việc thiết lập môi trường
  • Khi nhúng metadata PEP 723 vào tệp Python, việc tự động chạy script và quản lý gói trở nên thuận tiện hơn
  • Với ví dụ script thực thi, có thể nhanh chóng triển khai và phát hành chương trình trích xuất phụ đề YouTube
  • Nhờ đó, giờ đây Python cũng có thể viết tệp thực thi đơn lẻ gọn gàng, giúp khả năng tận dụng script được cải thiện đáng kể

Tổng quan

  • Trước đây, khi chạy các "script dùng một lần (one-off)" trong Python, luôn phải trải qua bước thiết lập môi trường và cài gói mỗi lần, nhưng sự bất tiện đó đã biến mất nhờ uv và PEP 723
  • uv là trình quản lý gói và dự án Python tốc độ cao được phát triển bằng Rust; cùng với tính năng mới uvx, nó xử lý việc thiết lập môi trường ảo dùng tạm, tự động cài gói và liên kết phiên bản Python rất nhanh và đơn giản

Ưu điểm của uv và uvx

  • Tính năng uvx hoạt động tương tự npx trong hệ sinh thái Nodejs, nhanh chóng tạo môi trường để chạy gói Python được chỉ định (ví dụ: ruff)
  • Tận dụng disposable virtual environment dưới dạng bộ nhớ đệm để mang lại khả năng thực thi nhanh mà không phát sinh overhead
  • Việc thiết lập môi trường và cài phụ thuộc được thực hiện chỉ bằng một dòng lệnh, nên lập trình viên không cần tự quản lý cấu hình môi trường riêng

Giới thiệu và cách dùng PEP 723

  • PEP 723 định nghĩa tiêu chuẩn cho phép đưa metadata về phụ thuộc và môi trường vào đầu script Python
  • Ví dụ: có thể khai báo requires-python, dependencies ở phần đầu mã
  • Các công cụ bên ngoài nhận diện được điều này (như uv) sẽ tự động xử lý cài đặt, thiết lập môi trường và thực thi dựa trên thông tin được viết ngay trong tệp script

Kết hợp uv và PEP 723

  • Khi viết metadata tương ứng ở đầu một tệp Python mẫu và chạy bằng lệnh uv run, tất cả gói cần thiết sẽ được tự động cài đặt ngay, phiên bản Python được chỉ định cũng được thiết lập trước khi mã được thực thi
  • Mã ví dụ gọi một API trên Internet (danh sách PEP) và in ra kết quả. Có thể chạy chỉ bằng một dòng lệnh mà không cần cài thêm gói hay cấu hình môi trường

Ví dụ thực tế: script phụ đề YouTube

  • Cung cấp ví dụ script Python có thêm shebang(#!/usr/bin/env -S uv run --script) và metadata PEP 723
  • Tự động cài các gói bên ngoài như youtube-transcript-api và tự động thiết lập môi trường ảo
  • Người dùng chỉ cần truyền URL hoặc ID video Youtube làm đối số cho tệp thực thi (ytt), script sẽ trích xuất phụ đề và trả kết quả ngay lập tức
  • Sau khi cấp quyền thực thi bằng chmod, có thể chạy dễ dàng trong terminal

Cải thiện trải nghiệm lập trình viên và mở rộng khả năng

  • Trước đây, ngay cả với việc chạy script đơn giản, người ta thường ưu tiên các ngôn ngữ tạo binary thực thi đơn lẻ như Go; nhưng giờ Python cũng mang lại mức độ tiện lợi tương đương
  • Sự kết hợp giữa uv và PEP 723 giúp việc chia sẻ, phát hành và tự động hóa thực thi script Python trở nên dễ dàng hơn rất nhiều
  • Có thể phát triển các trường hợp sử dụng phức tạp hơn thông qua ví dụ trên Github (cottongeeks/ytt-mcp)

2 bình luận

 
ndrgrd 2025-06-25

uv nhanh kinh khủng nên dùng rất sướng. Dạo này tôi đang dùng uv ở mọi nơi có thể.

 
GN⁺ 2025-06-25
Ý kiến trên Hacker News
  • Giống tác giả bài viết, dạo này tôi cũng hay tìm đến các script Python đa nền tảng dùng một lần và script cá nhân hơn là Go, nhưng vẫn thấy không hài lòng vì hệ thống kiểm tra kiểu của Python đúng là hỗn loạn; hy vọng các công cụ như ty, pyrefly sẽ cải thiện được phần nào

  • Giờ thì có cảm giác script Python chạy ngay ngon lành mà không còn phải khổ sở vì virtualenv nữa Tôi cũng ước phía shell script có được trải nghiệm như vậy Đóng gói, quản lý phụ thuộc và khả năng tái lập vẫn như đang ở thời kỳ đồ đá Hiện thực bây giờ vẫn là hoặc phó mặc cho số phận với curl | bash, hoặc chỉ có một file README chứa 3 phụ thuộc bị thiếu và 12 bước thủ công Nix? Cảm giác như chỉ là lựa chọn dùng được cho những ai đã siêu thoát khỏi thời gian, không gian và cả cuốn hướng dẫn Nix Docker? Nếu thấy việc tải hẳn một bản phân phối Linux chỉ để chạy một lệnh sed là hợp lý thì đó cũng là một lựa chọn ổn Thật sự cần một điểm trung gian đơn giản, mang tính khai báo, mà ai cũng có thể dùng dễ dàng

    • Tôi thích cách chỉ viết shell script dùng đúng các binary và thư viện có sẵn mặc định trên OS đích Mục tiêu làm shell script có tính di động thực tế là một lựa chọn không phù hợp Nếu phải chạy một shell script dùng lệnh chỉ có trên macOS ở Linux, thì không package manager nào giải quyết nổi vấn đề đó
    • Nix cho mục đích này thực ra không khó dùng đến vậy Nếu cài Nix trên distro khác thì có thể dùng đơn giản theo kiểu như sau Toàn bộ NixOS hay hệ đóng gói Nix thì khá thử thách, nhưng nếu chỉ giới hạn ở shell script thì rào cản gia nhập tương đối thấp
    • Tôi không thấy cần phải viết shell script mới cho bằng được Nếu đang ở môi trường cho phép cài mọi phụ thuộc thì công cụ như uv sẽ xử lý hết Nếu thích Clojure thì cũng khuyên dùng babashka
    • Lý do đóng gói, quản lý phụ thuộc và khả năng tái lập trong shell script trông như từ thời tiền sử là vì nếu bạn cần đến mấy thứ đó, thì shell có lẽ không còn là lựa chọn phù hợp nữa Tôi cho rằng shell chỉ hợp với các script nhỏ cỡ khoảng 20 dòng trở xuống Bản thân ngôn ngữ này không đủ chất lượng để phù hợp với quy mô lớn hơn
    • Đề xuất mise Công ty tôi đang dùng nó để quản lý môi trường phát triển, và việc dựng môi trường đơn giản hơn Docker lẫn Nix rất nhiều Hỗ trợ cài đặt song song nên cảm nhận là có lợi thế lớn hơn Dockerfile thông thường
  • Đây thật sự là một xu hướng rất tuyệt và có cảm giác ngày càng phổ biến hơn Tôi biết đến nó lần đầu qua blog của simonw, và có thể xem thêm ở bài blog của simonwillison Hồi tháng 3 năm nay cũng đã có thảo luận trên Hacker News về một bài blog khác Mong là xu hướng này sẽ ở lại trang chính đủ lâu để nhiều người biết đến hơn

  • Tôi đã thử dùng uv cho các dự án nhỏ và trải nghiệm thật sự xuất sắc Kết hợp uv runuv tool run (uvx) giúp việc cài rồi chạy ngay các script Python trên GitHub trong VM trở nên cực kỳ đơn giản Không cần git clone, không cần tạo hay chui vào venv, cũng không cần pip install Quan trọng hơn cả là uv nhanh đến mức ban đầu tôi còn tưởng có gì đó sai sai; thực tế thì kết quả nhanh hơn pip 10 lần Dù vậy công cụ và tài liệu vẫn còn hơi chưa hoàn thiện, nhưng với mức độ đột phá và tính thực dụng như vậy thì vẫn quá đáng để dùng

    • Tôi thật sự kinh ngạc khi uv cài phụ thuộc còn nhanh hơn cả thời gian pyenv in ra --help
  • Rust cũng đang phát triển ý tưởng shell script kiểu single-file tương tự thế này Ban đầu tôi thấy kiểu làm này ở Rust trước tiên (hỗ trợ chạy file đơn kèm quản lý phụ thuộc) Tôi hy vọng mô thức này sẽ được nhiều ngôn ngữ khác tiếp nhận hơn, vì nó cực kỳ hữu ích để chia sẻ qua gist hoặc viết các công cụ nhỏ thật nhanh Xem thêm tài liệu RFC của cargo-script

  • Khi dùng uv run --script, nếu nhúng metadata vào script thì việc mở ngay Python REPL từ script để sửa và thử hơi bất tiện Ví dụ phải làm như sau,

    $ uv run --python=3.13 --with-requirements <(uv export --script script.py) -- python
    >>> from script import X
    

    Tôi mong có cách nào ngắn gọn hơn Ví dụ nếu có thể làm như

    $ uv run --with-script script.py python
    

    thì sẽ là tốt nhất, nhưng trên thực tế nếu chạy như dưới đây thì có thể vào thẳng môi trường Python và venv phù hợp với script

    $ "$(uv python find --script script.py)"
    >>> from script import X
    

    Tuy vậy cần chạy script ít nhất một lần để tạo môi trường

    • Nếu cần tính năng gọi REPL sau khi thiết lập, có thể tham khảo ví dụ gist này Có thể thêm cờ như --interactive vào script để biến nó thành tùy chọn CLI Tôi thường viết các CLI nhỏ dựa trên Typer theo kiểu này Với script dev, tôi từng có trải nghiệm dùng cờ --sql để vào DuckDB SQL REPL
    • Giới thiệu một cách đơn giản
      cat ~/.local/bin/uve
      #!/bin/bash
      temp=$(mktemp)
      uv export --script $1 --no-hashes > $temp
      uv run --with-requirements $temp vim $1
      unlink $temp
      
  • Nếu dùng conda, có thể kích hoạt môi trường trực tiếp trong shell wrapper cho script Python Viết như sau

    #!/usr/bin/env bash
    eval "$(conda shell.bash hook)"
    conda activate myenv
    python myscript
    

    Tuy nhiên, đây không phải cách tiếp cận độc lập như kiểu PEP 723

  • Sau khi xem thread HN hôm qua và hôm nay, tôi quyết định thử uv lần đầu, và thật sự ấn tượng với tốc độ nhanh cùng việc quản lý phụ thuộc dễ dàng Sẽ còn tốt hơn nữa nếu tài liệu chính thức được cải thiện, đặc biệt là có hướng dẫn chuyển từ workflow requirements.txt sang uv thì sẽ tiện hơn Phần chỉ định phiên bản Python theo dự án hơi gây rối (định nghĩa ở cả .python-versionpyproject.toml)

    • Tôi từng viết ebook dạng khám phá các công cụ dành cho lập trình viên Python Trước đây tôi có hướng dẫn những chỗ mà tài liệu chính thức còn thiếu, cách migrate từ requirements.txtcách đổi phiên bản Python của dự án uv cũng đáng tham khảo Nếu có chủ đề nào khác nên được đề cập thêm thì cứ đề xuất
    • Trường requires-version trong pyproject.toml mang nghĩa phạm vi phiên bản được đảm bảo tương thích, còn .python-version chỉ định phiên bản cụ thể dùng cho phát triển Khi tạo bằng uv init thì lúc đầu chúng trông có vẻ giống nhau, nhưng theo thời gian thì requires-version sẽ chỉ định phiên bản tối thiểu được hỗ trợ thấp hơn .python-version requires-version cũng đi vào metadata của package và ảnh hưởng đến việc giải quyết phụ thuộc của người khác khi dùng package bạn phát hành Ví dụ như v1 còn hỗ trợ Python bản 3 cũ, nhưng v2 thì không nữa
    • Tôi cũng có cảm giác tương tự, nhưng vẫn cố chấp giữ workflow riêng của mình (đồng bộ cùng một file qua Dropbox lên mọi máy và dùng không phụ thuộc nền tảng) Với npm hay dotnet, khi đổi nền tảng thì cần npm update hoặc dotnet restore, nhưng venv vẫn hoạt động ổn không vấn đề gì Còn uv thì khi đổi nền tảng theo kiểu này có vẻ phức tạp hơn và cần dọn dẹp thủ công nhiều hơn
    • pyproject.toml (không riêng gì uv) nhằm mục đích định nghĩa môi trường cần thiết khi chia sẻ mã với nhà phát triển và người dùng bên ngoài Khi build package cho PyPI thì nó dùng để khai báo cần môi trường nào, và phạm vi phiên bản cũng được đặt để mở rộng mức độ tái sử dụng mã cho nhiều người Còn .python-version chỉ để uv tham chiếu khi thiết lập môi trường phát triển của riêng tôi Nếu đã có sẵn môi trường được tạo từ trước thì không nhất thiết phải cấu hình lại uv vẫn chưa là build backend chính thức, nhưng đang chuẩn bị cho tính năng đó (issue #3957)
    • Tôi chưa tìm hiểu thật kỹ, nhưng đoán rằng vai trò của file .python-version chủ yếu là để tương thích với các công cụ khác không có TOML parser
  • Trước đây tôi từng muốn tạo một công cụ để script Python tự cài phụ thuộc (mục tiêu là công cụ hoạt động kiểu uvx, nhưng chỉ cần có Python là chạy được) Tuy vậy nhược điểm là phải chèn nhiều dòng trông khá kỳ ở đầu script Nếu tò mò thì nó đang được phát hành trên PyPI với tên pysolate

    • Có cả dự án isolate khá giống nhưng không được dùng rộng rãi lắm Cách làm có hơi khác, nhưng vẫn là một ví dụ tiếp cận thú vị
  • Một kiểu thông điệp theo phong cách Grace Hopper lấy cảm hứng từ COBOL Cần có văn hóa mọi chương trình Python đều định nghĩa một ENVIRONMENT division để ghi rõ môi trường biên dịch và chạy (bao gồm cả yêu cầu phần cứng, phần mềm) Cấu trúc như vậy sẽ có tác động quyết định trong việc cải thiện tính di động của chương trình giữa nhiều hệ thống khác nhau