2 điểm bởi GN⁺ 5 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • uv có thế mạnh về tốc độ, quản lý phiên bản Python và tích hợp nhiều công cụ vào một binary duy nhất, nhưng UX quản lý gói ở giai đoạn bảo trì vẫn còn khá thô
  • Có thể kiểm tra các gói cũ bằng uv pip list --outdated, nhưng vì nằm dưới namespace tương thích pip thay vì là lệnh cấp cao nhất, nên khả năng được phát hiện khá thấp
  • uv add pydantic mặc định thêm ràng buộc không có cận trên như pydantic>=2.13.4, nên cả việc tăng major version cũng được cho phép
  • Việc nâng cấp toàn bộ được xử lý bằng uv lock --upgrade, còn khi nâng cấp nhiều gói cụ thể thì cần lặp lại --upgrade-package, khiến câu lệnh trở nên dài dòng
  • Có thể dùng cấu hình add-bounds = "major" để tạo ràng buộc mặc định an toàn hơn, nhưng đây vẫn là tính năng preview và ứng dụng vẫn cần UX cập nhật trực quan hơn

Điểm mạnh của uv và sự bất tiện trong giai đoạn bảo trì

  • uv của Astral mạnh ở tốc độ cao, quản lý phiên bản Python và khả năng thay thế nhiều công cụ bằng một binary duy nhất
  • Quy trình bắt đầu một dự án Python mới và thêm phụ thuộc đầu tiên thì khá dễ, nhưng khi dự án bước vào giai đoạn bảo trì, UX kiểm tra gói cũ và nâng cấp định kỳ lại cho cảm giác thô hơn pnpm hay Poetry
  • Các bất tiện chính nằm ở khả năng phát hiện lệnh kiểm tra gói cũ, việc thiếu cận trên trong ràng buộc phiên bản mặc định và sự dài dòng của lệnh nâng cấp

Kiểm tra các gói đã cũ

  • Trong các dự án JavaScript, có thể dùng pnpm outdated để xem ngắn gọn các gói đã cũ, phiên bản hiện tại, phiên bản mới nhất và phiên bản được phép theo điều kiện ràng buộc
  • uv không có lệnh cấp cao nhất uv outdated, và ban đầu lệnh sau được dùng như một phương án thay thế
$ uv tree --outdated --depth 1
  • uv tree --outdated --depth 1 không chỉ lọc ra các mục đã cũ mà còn in ra toàn bộ cây phụ thuộc cấp cao nhất, rồi gắn một chú thích nhỏ cạnh những mục có thể cập nhật
  • Dù có 50 phụ thuộc mà chỉ 2 gói đã cũ, bạn vẫn phải rà qua danh sách 50 dòng
  • poetry show --outdated của Poetry cũng có tên lệnh kém trực quan hơn, nhưng đầu ra thực tế chỉ hiển thị các gói đã cũ

Rủi ro của ràng buộc phiên bản mặc định

  • Cách mặc định của pnpm và Poetry

    • pnpm add ghi vào package.json một yêu cầu dạng caret như ^1.23.4
    • ^1.23.4 cho phép các phiên bản 1.x.x nhưng không cập nhật lên 2.0.0
    • Poetry cũng mặc định dùng dạng như >=1.23.4,<2.0.0; cách viết kém dễ đọc hơn nhưng hiệu quả là như nhau
    • Với hai công cụ này, nếu giả định gói tuân thủ SemVer thì ngay cả khi chạy pnpm update hay poetry update, khả năng build bị hỏng do thay đổi API lớn cũng được giảm xuống
  • Cách mặc định của uv

    • uv add pydantic thêm vào pyproject.toml một ràng buộc không có cận trên như sau
dependencies = [
    "pydantic>=2.13.4",
]
  • Với ràng buộc này, các phiên bản pydantic 2, 3 hay 100 đều được chấp nhận
  • Khi chạy cập nhật hàng loạt, bạn không chỉ nhận các bản vá lỗi mà còn có thể nhận cả những thay đổi phá vỡ tương thích do mọi maintainer trong đồ thị phụ thuộc phát hành
  • Điều này đặc biệt có thể dẫn tới rủi ro về độ ổn định trong quá trình bảo trì ứng dụng

UX của lệnh nâng cấp

  • Trong pnpm và Poetry, cập nhật toàn bộ rất đơn giản như sau
$ pnpm update
$ poetry update
  • Trong uv, lệnh sau được dùng để nâng cấp toàn bộ
$ uv lock --upgrade
  • uv lock --upgrade không phải uv update hay uv upgrade mà hoạt động như một tùy chọn của lệnh lock, nên với góc nhìn là lệnh quản lý gói dành cho con người, nó kém trực quan hơn
  • Khi kết hợp với ràng buộc không có cận trên, uv lock --upgrade trở thành lựa chọn nâng tất cả các gói trong lockfile lên phiên bản mới nhất tuyệt đối
  • Bản cập nhật này có thể bao gồm cả các phụ thuộc lồng sâu mà bạn thậm chí không trực tiếp biết tới
  • Nếu chỉ muốn cập nhật một số gói cụ thể, pnpm cho phép liệt kê tên gói như sau
$ pnpm update pydantic httpx uvicorn
  • Còn trong uv, bạn phải lặp lại cờ --upgrade-package cho từng gói
$ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn
  • Khi cần nâng nhiều gói cùng lúc, việc lặp lại cờ này trở thành một phiền toái lớn

Cờ --bounds và cấu hình

  • Gần đây, uv đã thêm tùy chọn --bounds cho uv add
$ uv add pydantic --bounds major
  • Lệnh này tạo ra ràng buộc an toàn hơn là pydantic>=2.13.4,<3.0.0
  • --bounds major hiện vẫn là tính năng preview và là tùy chọn opt-in phải nhập thủ công cho từng lệnh
  • Sau đó, người ta phát hiện có thể đặt giá trị mặc định một lần trong pyproject.toml
[tool.uv]
add-bounds = "major"
  • Với cấu hình này, bạn không cần nhập --bounds major mỗi lần nữa mà các lệnh uv add sau đó sẽ có mặc định hợp lý hơn
  • Với ứng dụng, sẽ tốt hơn nếu đây là hành vi mặc định, nhưng mức độ tiện dụng thực tế không tệ đến như mô tả ban đầu

Sự khác biệt giữa ứng dụng và thư viện

  • Lời khuyên chuẩn trong hệ sinh thái đóng gói Python là thư viện phát hành lên PyPI không nên cố định cận trên, và lời khuyên này là hợp lý
  • Nếu mọi thư viện đều cố định cận trên, cây phụ thuộc của downstream consumer có thể không giải được
  • Ngược lại, ứng dụng là nút cuối của đồ thị phụ thuộc và không có người dùng khác giải phụ thuộc dựa trên các ràng buộc đó
  • Với ứng dụng, việc đặt cận trên không có chi phí nhưng lại giúp bảo vệ khỏi những lần tăng major version ngoài dự kiến
  • Phạm vi ở đây là việc bảo trì các ứng dụng như website, dịch vụ hay công cụ nội bộ; còn với việc phát hành thư viện thì mặc định không có cận trên có thể là hợp lý

Những phần đã được đính chính và các vấn đề còn lại

  • Có thể dùng uv pip list --outdated để chỉ xem các gói đã cũ
$ uv pip list --outdated
  • Vì vậy, phê phán về đầu ra quá ồn của uv tree --outdated --depth 1 đã yếu đi
  • Vấn đề còn lại là tính năng này không phải lệnh cấp cao nhất mà nằm dưới namespace tương thích pip, nên khả năng được phát hiện vẫn thấp
  • Có thể dùng cấu hình add-bounds = "major" để đặt bounds mặc định, nên cách nhìn rằng hoặc phải tự tay chỉnh cận trên mọi lần hoặc phải chấp nhận rủi ro là không hoàn toàn đúng
  • Dù vậy, đây vẫn là tính năng preview, và trong quản lý gói cho ứng dụng vẫn cần ràng buộc mặc định an toàn hơn cùng lệnh cập nhật trực quan hơn

Hướng cải thiện mong muốn

  • Cần một lệnh uv outdated chuyên dụng hiển thị rõ ràng chỉ các gói đã cũ
  • Cần một lệnh update công thái học hơn để cập nhật nhiều gói mà không phải lặp lại cờ
  • Ràng buộc phiên bản mặc định nên phản ánh tốt hơn kỳ vọng ổn định của semantic versioning (SemVer)
  • Ở trạng thái hiện tại, gánh nặng phải nghi ngờ và kiểm tra từng dòng thay đổi trong lockfile vẫn còn đó

1 bình luận

 
Ý kiến trên Hacker News
  • Phạm vi phiên bản mặc định của uv add có thể được đặt thành cấu hình cố định nên không cần truyền mỗi lần
    Tham khảo: https://docs.astral.sh/uv/reference/settings/#add-bounds
    Lý do mặc định không thêm cận trên là vì điều đó tạo ra rất nhiều xung đột không cần thiết trong hệ sinh thái, và hồi còn dùng Poetry tôi cũng từng tổng hợp tài liệu liên quan ở đây: https://github.com/zanieb/poetry-relax#references

    • Tôi hiểu rằng khi phát hành thư viện thì việc loại bỏ phiên bản cận trên là quan trọng, nhưng bài viết này được viết từ góc nhìn xây dựng website chứ không phải thư viện
      Khi dùng dependency trong một dự án web, tôi muốn có cận trên để ngăn thay đổi phá vỡ, với giả định dependency tuân thủ SemVer
    • Cộng đồng Haskell cũng vật lộn với vấn đề này suốt nhiều năm, và cách tiếp cận từng thành công nhất là Stackage
      Họ khuyến khích không thêm cận trên phòng thủ, liên tục build một phần lớn và năng động của hệ sinh thái ở mỗi bản phát hành để tìm ra vấn đề tương thích thực tế, tự động gửi thông báo cho chủ sở hữu, và cung cấp lịch trình rõ ràng để được giữ lại trong bản phát hành "LTS" tiếp theo
      Giờ đây chỉ riêng bộ giải Cabal dường như cũng đã khá ổn định, nhưng các bản build nightly trên phạm vi rộng cùng những lỗi và chặn hiển thị rõ ràng hẳn đã giúp hệ sinh thái tiếp tục giữ được khả năng giải quyết phụ thuộc
    • Tôi mới biết đến thiết lập add-bounds, và việc khóa chính xác dependency là quan trọng, nhưng nó cũng hữu ích cho các dự án mà lập trình viên ít kinh nghiệm dễ bỏ sót, đặc biệt là sản phẩm hoàn chỉnh chứ không phải thư viện
    • Tôi muốn biết có cách nào đặt vĩnh viễn cờ --native-tls không
      Vì cấu hình Zscaler ở công ty nên UV luôn thất bại nếu không có cờ này
      Tôi cũng muốn biết liệu có kế hoạch hỗ trợ chỉ định phiên bản Python tương thích cho một kiến trúc cụ thể hay không. Có một gói do công ty tôi duy trì bắt buộc phải dùng Python 32-bit nên lúc nào tôi cũng phải truyền --python /path/to/32bit
    • Có thể đây là câu hỏi hơi thiếu trau chuốt, nhưng tôi muốn biết có cách nào để uv tôn trọng exclude-newer trong pyproject.toml không
      Khi chạy uv run, exclude-newer bị xóa khỏi pyproject.toml
      Tôi có thể chạy uv run —-frozen hoặc uv run --exclude-newer mỗi lần, nhưng điều đó không có vẻ là luồng làm việc đúng đắn, nên tôi muốn biết liệu có cách làm mang tính quy ước nào mà tôi đang bỏ sót không
  • uv được thiết kế không có cận trên vì nó cần một kết quả giải duy nhất
    npm có thể cài các kết quả giải khác nhau ở những phần khác nhau của cây phụ thuộc, nhưng trong Python thì đó không phải một lựa chọn. Với Rye cũng phải đưa ra quyết định tương tự, và không có giải pháp nào tốt hơn
    Nếu thêm cận trên thì trên thực tế có thể xuất hiện những cây phụ thuộc không còn giải được nữa. Một số hệ sinh thái package của Python trước đây thậm chí đã phát hành override cho các package cũ được phát hành với giả định sai về cận trên
    Ở thời điểm hiện tại, bạn không thể biết package của mình có tương thích với một package chưa được phát hành hay không

    • Cá nhân tôi thấy tốt hơn nếu khi cập nhật, uv báo lỗi rằng các package không tương thích và tôi có thể override khi cần
      Như vậy vẫn tốt hơn là gặp lỗi không tương thích phiên bản lúc runtime mà rất khó lần theo
    • Việc không có cận trên trong pyproject.toml không phải vấn đề thật sự
      Vấn đề thật sự là uv lock —-upgrade nâng cấp hàng loạt mọi thứ không có cận trên
      Nếu có cách nâng cấp package mà không tăng major version thì lệnh này sẽ an toàn hơn nhiều
    • uv đã cải thiện rất nhiều thứ, nhưng về căn bản có lẽ vẫn còn khá nhiều điểm mà chỉ công cụ thôi không giải quyết nổi
      So với thời trước uv thì tốt hơn rất nhiều, nhưng để mọi thứ thật sự ổn có lẽ sẽ cần cả hệ sinh thái chấp nhận một mức độ thay đổi phá vỡ nhất định. Nghĩ đến giai đoạn chuyển từ Python 2 sang 3 thì có vẻ cũng chưa ai mặn mà với kiểu thay đổi đó trong tương lai gần
    • Điều đó đúng với tác giả thư viện, nhưng khi xây dựng website và phụ thuộc vào nhiều package thì tôi muốn có cận trên để an toàn khi nâng cấp
      Cờ —-bound có ích, nhưng lại là thêm một thứ phải gõ và phải nhớ
      Nếu uv có thể biết dự án đó không phải thư viện thì có lẽ mặc định thêm cận trên cũng là một cách
    • Thực ra cách dùng đúng với cả uv lẫn npm là đổi tất cả sang = rồi chỉ cập nhật thủ công, đừng tin rằng các bản cập nhật không tăng major sẽ không làm hỏng gì
  • Tôi có 257 dependency Python trong một ứng dụng đang chạy production, trong đó hơn một nửa là dependency trực tiếp
    Tôi không đặt cận trên trong pyproject.toml, và cứ mỗi 2 tuần lại chạy uv lock --upgrade bằng GitHub Actions
    Vì test coverage tốt nên nếu có gì hỏng thì test sẽ fail, và còn có cả quy trình review có AI hỗ trợ. Khi PR nâng cấp được tạo ra, một workflow AI sẽ dùng script Python để liệt kê các bản cập nhật major và minor, tìm changelog rồi gắn link và tóm tắt, đồng thời phân tích mức độ rủi ro của từng package dựa trên cách package đó được dùng trong codebase
    Nhìn chung hầu như không đau đớn gì, và không cần nâng cấp từng package một, kiểm tra package cũ hay xử lý dependency bị bỏ quên. Trường hợp hiếm hoi cần sửa từ phía tác giả dependency nên không thể giải quyết trong code của mình chỉ xảy ra khoảng 1 lần mỗi năm. Trong 3 tháng qua đã có 18 lần tăng major version, và chỉ một lần cần thay đổi code
    Tôi cũng muốn làm vậy ở frontend, nhưng test chưa đủ để chạy an toàn. Test ở backend dễ viết hơn và quan trọng hơn, nên tôi nghĩ mọi codebase đều nên có. Nếu có test, bạn có thể cứ thế tự động nâng cấp toàn bộ

    • Viết test cũng là việc mà AI agent làm khá tốt
      Ít nhất thì chúng rất giỏi trong việc biến chỉ dẫn ngôn ngữ tự nhiên thành test chính xác
      Tôi đã lâu không còn phải tự viết test bằng tay, mà ngày xưa đó luôn là việc tôi hay than phiền, giờ thì không còn nữa
  • UV đã làm được nhiều điều cho Python, nhưng hôm nay tôi đã phải vật lộn khá nhiều
    Tôi đang cố quản lý tập trung các script nằm rải rác ở nhiều repo và theo thời gian đã được triển khai theo những cách khác nhau
    Cách tôi nghĩ tới là uv run --with $package main --help, và tôi muốn nó tự động 1) cài rồi chạy nếu chưa có, 2) không cài nếu đã là bản mới nhất, 3) nếu chưa mới nhất thì cập nhật
    Nhưng cả ba điều đó đều khó hơn mong đợi. Về cơ bản uv run cài lại mỗi lần, và mất 6 giây cho virtualenv cùng việc cài đặt
    uvx hay uv tool cũng không khá hơn bao nhiêu, mà còn phát sinh vấn đề mới là người dùng không nhận được nâng cấp
    Cuối cùng tôi viết script để gọi paginated GET tới CodeArtifact, nếu có bản non-dev mới hơn thì cập nhật rồi chạy lại. Nó hoạt động, và độ trễ 200ms vẫn tốt hơn 6 giây, nhưng đó không phải trải nghiệm tôi mong muốn

    • Tôi hơi bối rối vì uv run --with $package main --help lẽ ra phải cho đúng hành vi bạn nói với rất ít overhead
      Nó không cài lại mỗi lần, và môi trường --with được giữ trong cache. Kể cả khi môi trường chưa được cache thì dependency vẫn được cache, và cài từ cache là rất nhanh. Chắc chắn phải dưới 200ms
      Nếu bạn mở một ví dụ tái hiện chi tiết thì chúng tôi có thể xem thử
    • Với trường hợp đó thì uv tool installuv tool upgrade có vẻ phù hợp
      Dù vậy, kiểu khó chịu nhỏ này có lẽ giải quyết khá dễ, nên nếu bạn mở issue thì sẽ rất tốt
    • Bạn cũng có thể định nghĩa các dependency cần thiết trong khối tài liệu ở đầu file rồi chỉ chạy uv run main
      Khi đó nó sẽ tự động cài, cache và chạy các dependency cần thiết: https://docs.astral.sh/uv/guides/scripts/
    • Có lẽ người dùng chỉ cần chạy uv tool upgrade là được?
    • Cũng đáng xem https://copier.readthedocs.io/en/stable/
      Tôi không chắc đó có đúng y hệt use case này không, nhưng nó từng rất hiệu quả với tôi trong việc đồng bộ hệ sinh thái microservice polyrepo
  • Tôi khá ngạc nhiên khi thấy người ta khuyên dùng "uv tree --outdated --depth 1" để xem danh sách dependency cũ
    Cá nhân tôi từ khi tính năng này ra đời đến giờ vẫn dùng "uv pip list --outdated"
    Dù vậy tôi đồng ý rằng một lệnh quan trọng đến mức này xứng đáng có subcommand cấp cao nhất riêng

    • Từ góc nhìn của tác giả bài viết, đó không hẳn là khuyến nghị mà chỉ là cách duy nhất họ biết
      Đúng là "uv pip list --outdated" cho đầu ra tốt hơn nhiều, cảm ơn vì điều đó
      Nhưng việc có tới 2 cách để xem package cũ mà đầu ra lại khác biệt lớn cũng khiến tôi cảm thấy UX thật tệ
    • "uv tree -od1" có lẽ cũng chạy được
      Tuy vậy, một lời phê bình tương tự với các trình quản lý package như pacman là các lệnh dùng thường xuyên nên có câu lệnh dễ hiểu với con người như apt
  • So với chữ “tệ” trong tiêu đề thì ví dụ đưa ra chỉ ở mức phải thêm vài tham số nữa thôi
    Có lẽ tiêu đề phù hợp hơn sẽ là những cải thiện chất lượng sống tôi muốn có ở UV

    • Cách dùng từ đó và những cụm như “ai đã thiết kế giao diện dòng lệnh này vậy” có vẻ nhằm thu hút chú ý và click
      Bản thân phản hồi thì hữu ích và tôi đồng ý với phần lớn, nhưng kiểu diễn đạt đó làm giảm giá trị của phản hồi và dễ gây phản ứng phòng thủ
      Cá nhân tôi cũng thấy giao diện dòng lệnh của uv hơi phiền, nhưng tôi hiểu tại sao nó lại được viết như thế
  • uv rất tuyệt, nhưng vấn đề lớn nhất của Python packaging hiện nay vẫn là xử lý tốt packaging cho khoa học/máy học
    Nếu muốn cài PyTorch thì trước hết phải xem là phiên bản nào, có CUDA hay không. Nếu có CUDA thì lại có 6 biến thể theo từng phiên bản CUDA, mà wheel còn quá lớn để đưa lên PyPI nên phải tải trực tiếp
    Conda chỉ giải quyết phần nào bài toán này. Spack thì cấu hình được cực kỳ sâu và có thể chuẩn bị đủ dependency C/C++/Fortran cùng toolchain compiler cần thiết để đạt hiệu năng tối đa, nhưng lại không tích hợp tốt với uv và các công cụ tương tự. Vì thế rất khó đưa các dự án machine learning thử nghiệm do nhà nghiên cứu tạo ra lên production

    • Trước đây tôi từng lách bằng Anaconda, nhưng nó kéo theo quá nhiều thứ lặt vặt và môi trường phát triển lại hoàn toàn khác môi trường vận hành, nên cách đó cũng không ổn
      Rồi cuối cùng vẫn quay về tình huống đã nói ban đầu
  • Có khá nhiều phản hồi hữu ích, nhưng cũng lẫn chút giật tít
    Về pnpm outdated, đây không phải điều tôi thấy được nhắc nhiều, nhưng nghe như một yêu cầu hợp lý. Có lẽ nó đến từ khác biệt văn hóa giữa Python và JavaScript. Với dependency Python, trừ khi nó có lỗ hổng hoặc bị hỏng, tôi gần như chưa bao giờ quan tâm nó có cũ hay không; còn trong hệ sinh thái JavaScript, có vẻ việc tranh thủ nâng cấp khi có dịp là chuyện khá phổ biến. Điều này không có nghĩa là xấu, mà cho thấy trực giác về việc nên đưa gì ra giao diện dòng lệnh có thể khác nhau đến mức nào giữa các cộng đồng lập trình lớn
    Như Armin đã nói, hành vi cận trên của uv là có chủ đích, và về mặt chức năng là cần thiết theo cách Python giải quyết dependency. Đó là một đánh đổi mà Python chọn so với các ngôn ngữ khác, nhưng tôi thấy đây là đánh đổi tốt ở chỗ mỗi dependency trong cây chỉ có một bản duy nhất và mọi yêu cầu ràng buộc lẫn nhau đều được giải trên cơ sở đó
    Lý do uv lock --upgrade hoạt động như vậy là vì nó nâng cấp lock file, chứ không phải các yêu cầu do người dùng khai báo. Trong khi đó pnpm update dường như nâng cấp các yêu cầu người dùng trong package.json. Có thể gây nhầm lẫn, nhưng đặt nó dưới uv lock thì chính xác hơn. Nếu không, sẽ có người thắc mắc vì sao uv upgrade lại không nâng cấp theo kiểu mà họ nghĩ. Dù vậy vẫn còn dư địa để trình bày gọn gàng hơn, và rõ ràng đã có nhu cầu từ người dùng về một subcommand uv chuyên nâng cấp trực tiếp các yêu cầu
    https://news.ycombinator.com/item?id=48230048

    • Tôi đồng ý về package cũ và cận trên, nhưng nếu người dùng than phiền giao diện khó dùng thì rõ ràng là có vấn đề
      Việc lệnh uv lock chỉ xử lý lock file là hợp lý, nhưng người dùng có nhu cầu thực tế là nâng cấp dependency trực tiếp và bắc cầu. Dependency bắc cầu thì làm được bằng uv lock --upgrade-package, nhưng hơi dài dòng. Nó cũng hoạt động với dependency trực tiếp, nhưng không đụng tới pyproject.toml, trong khi file này lại dễ được lập trình viên nhìn thấy hơn nhiều
      Nếu phiên bản package trong uv.lock đi trước pyproject.toml, thì pyproject.toml sẽ kém đáng tin hơn với vai trò là bản hướng dẫn để hiểu bề mặt dependency. Sẽ thật tốt nếu có một lệnh uv upgrade thân thiện
      Cái bẫy UX lớn nhất tôi thấy ở uv cho đến nay là uv pip. Nhiều dự án dùng uv đúng cách với pyproject.tomluv.lock trong phát triển, nhưng trong Dockerfile triển khai hoặc công cụ CI lại dùng uv pip install -r pyproject.toml, tức là đi vòng qua uv.lock
      Việc các coding agent có quá nhiều dữ liệu huấn luyện chứa pip nên hay đề xuất những mẫu uv pip tệ cũng là vấn đề, nhưng uv cũng nên cung cấp cơ chế bảo vệ người dùng
      Theo tôi uv là một công cụ tuyệt vời và nên được dùng rộng rãi hơn: https://aleyan.com/blog/2026-why-arent-we-uv-yet
    • Nếu từ góc nhìn của tác giả mà điều đó trông giống “giật tít” thì tôi xin lỗi, nhưng thực ra đó chỉ là sự thẳng thắn kiểu Hà Lan mà thôi
      poetry update cũng cập nhật lock file. Tôi thấy cách tổ chức CLI của uv khá phiền để làm việc. Nó tạo cảm giác được thiết kế cho độ chính xác và cho máy móc, chứ không phải cho sự thân thiện với người dùng
    • Với tư cách người chuyển từ pip sang uv, khi cần thông tin đó tôi lại quay về uv pip list --outdated
    • uv upgrade có trong roadmap
      Lý do nó chưa xuất hiện là vì rất khó tạo ra một trải nghiệm thực sự tốt, có nhiều sắc thái hơn mọi người tưởng rất nhiều, trong khi nhóm thì nhỏ và còn nhiều ưu tiên khác
    • Một trong những mục đích của tính năng kiểu pnpm outdated là xem điều gì sẽ được cập nhật nếu chạy "uv sync --update" hoặc "uv lock --update"
      Tuy nhiên, cũng có thể tốt hơn nếu những lệnh đó có prompt xác nhận
  • Pixi dùng uv làm backend, và tôi thích UI của nó vì rất dễ thêm alias tác vụ để liệt kê package cũ theo cách dễ đọc
    Đặc biệt, Pixi-diff-to-markdown giúp việc rà soát các bản cập nhật package tự động trong CI dễ hơn nhiều
    Nếu muốn xem trong số các package cũ thì những gì sẽ được cập nhật, bạn có thể tạo alias tác vụ như sau cho dự án
    pixi task add outdated "pixi update --dry-run --json | pixi exec pixi-diff-to-markdown"
    Sau đó chỉ cần chạy pixi run outdated trong dự án
    Đầu ra là một bảng Markdown dễ đọc, chứa các package sẽ được cập nhật, phiên bản hiện tại, và phiên bản mới sẽ được cài bởi lệnh pixi update. Dĩ nhiên, điều này còn tùy gu và bối cảnh

  • Gần đây script env đã xuất hiện trong đường dẫn và cản trở việc dùng lệnh UNIX env thông thường
    Hóa ra trình cài đặt uv tạo ra nó khi chạy lệnh dưới đây
    curl -LsSf [https://astral.sh/uv/install.sh](<https://astral.sh/uv/install.sh>;) | sh
    Nó cài vào $HOME/.cargo/bin/, rồi tạo một script shell ở $HOME/.cargo/env để thêm $HOME/.cargo/bin/ vào đầu PATH nếu đường dẫn đó chưa có sẵn
    Tôi thật khó hiểu nổi kiểu lập trình viên nào lại viết code ghi đè lệnh UNIX mặc định theo cách như vậy