So sánh hai trình kiểm tra kiểu Python mới dựa trên Rust: Pyrefly và Ty
(blog.edward-li.com)- Gần đây, hai trình kiểm tra kiểu Python dựa trên Rust là Pyrefly của Meta và Ty của Astral đã được công bố, cho thấy hiệu năng vượt trội và một mô hình typing mới so với mypy và pyright hiện có
- Pyrefly theo đuổi suy luận kiểu tích cực và định hướng mã nguồn mở, còn Ty giới thiệu nguyên tắc "gradual guarantee" nhằm giảm thiểu tối đa việc phát sinh lỗi kiểu
- Cả hai công cụ đều đang ở phiên bản alpha giai đoạn đầu, nhưng kết quả benchmark trên nhiều dự án cho thấy Ty trung bình chạy nhanh hơn
- Trong phân tích gia tăng, Pyrefly cung cấp cơ chế theo đơn vị mô-đun, còn Ty cung cấp mức gia tăng chi tiết theo hàm, nên khác nhau về cấu trúc và trải nghiệm sử dụng
- Ty giới thiệu hệ thống kiểu sáng tạo như intersection type và negation type, đồng thời cung cấp thông báo lỗi trực quan và rõ ràng hơn
Giới thiệu Pyrefly và Ty
- Pyrefly và Ty là các trình kiểm tra kiểu Python được phát triển bằng Rust
- Pyrefly do Meta (trước đây là Facebook) phát triển, nhằm thay thế Pyre vốn dựa trên OCaml
- Ty do Astral phát triển; Astral nổi tiếng với các công cụ Python như uv, ruff
- Cả hai dự án đều đã được công khai dưới dạng mã nguồn mở nhưng vẫn đang ở giai đoạn alpha trước phát hành chính thức
- Cả hai nhóm đều đã giới thiệu tầm nhìn, mục tiêu và cách tiếp cận của mình tại PyCon 2025 Typing Summit
Điểm giống nhau
- Cả hai đều được phát triển bằng Rust và hỗ trợ phân tích gia tăng (Incremental Checking)
- Đều sử dụng ruff để phân tích AST của mã Python
- Khả năng kết nối với môi trường phát triển cũng rất tốt, như kiểm tra kiểu trên dòng lệnh và tích hợp LSP/IDE
Khác biệt 1: tốc độ
Benchmark PyTorch
- Ty nhanh hơn Pyrefly khoảng 2~3 lần, và cả hai đều nhanh hơn mypy và pyright hiện có từ 10~20 lần
- Pyrefly đặt mục tiêu cải thiện hiệu năng gấp 35 lần so với Pyre, và gấp 14 lần so với mypy/pyright
- Ty được thiết kế với mục tiêu nhanh hơn các trình kiểm tra kiểu thế hệ hiện tại từ một đến hai bậc độ lớn
Benchmark Django
- Ty là nhanh nhất, tiếp theo là Pyrefly
- Pyright cho kết quả chậm hơn rõ rệt
Benchmark trên kho mã mypy
- Kết quả tương tự: Ty nhanh nhất, Pyrefly theo sau với khoảng cách nhỏ
- mypy và pyright ghi nhận thời gian thực thi chậm hơn đáng kể
Khác biệt 2: mục tiêu typing
Pyrefly
- Theo đuổi chiến lược suy luận kiểu tối đa có thể để bắt lỗi ngay cả khi mã không có khai báo kiểu tường minh
- Hướng tới tối đa hóa độ an toàn của mã bằng suy luận kiểu chủ động hơn
Ty
- Áp dụng nguyên tắc Gradual guarantee
- Được thiết kế để khi loại bỏ kiểu tường minh khỏi mã đang chạy đúng thì không phát sinh lỗi kiểu
- Không gây lỗi chỉ vì thiếu type annotation, và chỉ yêu cầu annotation bổ sung khi thực sự cần thiết
- Ví dụ: ngay cả khi gán giá trị vào một trường không có kiểu tường minh, công cụ cũng không báo lỗi kiểu mà xử lý dưới dạng
Unknown | None
Khác biệt 3: cách phân tích gia tăng
- Pyrefly: chỉ phân tích lại các tệp (mô-đun) đã thay đổi và các mô-đun phụ thuộc liên quan (gia tăng theo mô-đun)
- Ty: sử dụng framework Salsa của Rust để thực hiện gia tăng chi tiết đến cấp độ hàm
- Một bên cho rằng mức mô-đun là đủ nhanh, còn mức hàm có thể khiến codebase phức tạp hơn (khác biệt trong chiến lược của mỗi công cụ)
Khác biệt 4: tính năng (hệ thống kiểu và hỗ trợ)
Ưu điểm của Pyrefly
- Suy luận kiểu ngầm định rất mạnh
- Ngay cả không có kiểu tường minh, công cụ vẫn phân tích được các kiểu phức tạp như giá trị trả về của hàm, dictionary, list... để phát hiện lỗi
- Được thiết kế tập trung vào các bài toán typing phức tạp như generic, overload và wildcard import
- Độ chính xác trong suy luận generic tốt hơn Ty
Điểm đặc trưng của Ty
- Nhờ "gradual guarantee", công cụ cho phép kiểu thay đổi linh hoạt khi thiếu kiểu tường minh
- Hỗ trợ các hệ thống kiểu sáng tạo như intersection type và negation type
- Thông báo lỗi được thiết kế rất rõ ràng và trực quan
- Cho phép gán linh hoạt nhiều kiểu khác nhau vào list..., đồng thời đưa giá trị kiểu
Unknownvào hệ thống một cách chính thức
Hạn chế / trạng thái alpha
- Cả hai sản phẩm đều đang ở giai đoạn alpha, nên một phần suy luận kiểu hoặc tính năng vẫn chưa hoàn thiện
- Ví dụ, một số kết quả như suy luận kiểu list của Ty vẫn còn chưa đạt độ hoàn thiện cao
So sánh tính năng chi tiết
Suy luận kiểu ngầm định
- Pyrefly chủ động suy luận kiểu trả về và kiểu của các đối tượng collection, đồng thời hiển thị rõ revealed type và lỗi
- Ty sẽ trả về
Unknownhoặc@Todonếu khả năng inference chưa đủ
Generic
- Cả Pyrefly và Ty đều xử lý tốt các bài toán kiểu generic thông thường
- Pyrefly có ưu thế trong việc diễn giải kiểu của các instance được tạo mà không có type parameter
- Cả hai trình kiểm tra đều cho thấy điểm yếu hơn mypy và pyright trong các vấn đề covariance/contravariance
Thông báo lỗi
- Ty tập trung vào các thông báo lỗi ngắn gọn và dễ đọc
- So với Pyrefly, mypy và pyright, thông điệp của Ty dễ hiểu hơn ngay từ cái nhìn đầu tiên
Intersection / negation type
-
Chỉ Ty hỗ trợ intersection type (
&) và negation type (~), nhờ đó xử lý được các phép toán kiểu phức tạp như bên dưới- Ví dụ: với kiểu
WithX | Other, khi có thuộc tínhx, Ty sẽ tự động phân nhánh sangWithX - Ví dụ: khi không phải một subclass cụ thể, Ty diễn giải kiểu là
MyClass & ~MySubclass
- Ví dụ: với kiểu
-
Các intersection và negation type này là những tính năng rất tiên tiến trong lý thuyết kiểu
Các ví dụ nâng cao khác
- Ty còn có thể được dùng với hệ thống kiểu để xử lý các phép toán phức hợp như phương trình Diophantine
- Các bài test được viết bằng tài liệu Markdown (tham khảo: tài nguyên mdtest của Astral ruff)
Kết luận và triển vọng
- Hệ sinh thái Python đang chứng kiến sự xuất hiện của các trình kiểm tra kiểu mới cực nhanh
- Ty lấy độ an toàn kiểu theo hướng dần dần làm chiến lược chính, còn Pyrefly tập trung vào suy luận kiểu chủ động
- Vì cả hai còn ở giai đoạn đầu, vẫn còn nhiều khả năng để tính năng của chúng hội tụ hoặc tiếp tục tiến hóa trong tương lai
- Có thể dùng thử trên trang chính thức, và cũng đã có plugin cho các trình biên tập lớn như VSCode, Cursor
- Cũng có tin đồn rằng Google sẽ mã nguồn mở một trình kiểm tra kiểu dựa trên Go trong tương lai, nên lĩnh vực phân tích kiểu Python được kỳ vọng sẽ còn phong phú hơn nữa
Ứng dụng / tham khảo
- Pyrefly: pyrefly.org/sandbox
- Ty: play.ty.dev
- Ty của Astral sử dụng các bài test dựa trên Markdown (đường dẫn chi tiết xem mdtest trong repo ruff)
- Tài liệu chính thức, plugin cho editor và lệnh cài đặt gói cũng đều đã được cung cấp
2 bình luận
Có vẻ như với ty, nếu hàm đang dùng không ghi kiểu trả về thì mặc định luôn là
unknown; chỉ khi lưu lại thì nó mới kiểm tra cho bạn.Còn pyrefly thì dù không ghi cũng suy luận được, và còn kiểm tra ngay cả khi đang gõ.
Ý kiến trên Hacker News
Với tư cách là nhà phát triển của ty, nhấn mạnh rằng rất vui khi ty và pyrefly ngày càng được chú ý, nhưng cũng một lần nữa nhấn mạnh rằng cả hai dự án đều դեռ chưa ở giai đoạn hoàn thiện; cũng đã thấy các ví dụ do tính năng chưa được triển khai, nên mong mọi người hiểu rằng khi thấy “cái này kỳ vậy” thì thực ra có thể chỉ là phần đó vẫn chưa được phát triển; cần nhận thức rằng Python là một ngôn ngữ rất lớn và đa dạng
Có ý kiến nói rằng rất thích cách ty dùng kiểu test theo phong cách markdown; việc test đồng thời đóng vai trò như tài liệu là một ý tưởng cực hay; thắc mắc liệu ý tưởng này có được lấy cảm hứng từ các ví dụ mã được tài liệu hóa của Rust hay không
Bật cười khi thấy phần thể hiện kiểu được đánh dấu bằng
@TODO, nhưng nghĩ lại thì đây là một cơ chế khá dí dỏm và hữu íchVới kinh nghiệm TypeScript, thấy bản thân những thử nghiệm như suy luận kiểu, thu hẹp kiểu, cũng như việc mỗi trình kiểm tra kiểu Python lại hành xử khác nhau đều rất thú vị; vẫn thật sự cần một trình kiểm tra kiểu vừa nhanh vừa đáng tin cậy, nhưng Python có cảm giác đang tụt lại khá xa ở khía cạnh này; cho rằng trình kiểm tra kiểu nên nâng cao năng suất và độ tin cậy của mã, nên ủng hộ các dự án như vậy
Từ góc nhìn nhà phát triển Rust, đặt câu hỏi về một “ngôn ngữ script cho Rust”: có cộng đồng nào đang nghiên cứu một ngôn ngữ hợp với cú pháp Rust, có thể import native các kiểu Rust, và biên dịch/hot reload nhanh hay không; cũng muốn xin ý kiến liệu Python có thể đảm nhiệm vai trò này dù cú pháp khác đi chăng nữa; kèm liên kết liên quan https://news.ycombinator.com/item?id=44050222
Ý kiến từ góc nhìn bên ngoài, không có nhiều kinh nghiệm với Python: nếu quan tâm đến việc dùng type hint thì nên tham khảo bài Reddit https://www.reddit.com/r/Python/comments/10zdidm/why_type_hinting_sucks/; không nên quá nghiêm túc với bài đó, nhưng nhấn mạnh rằng dù công cụ kiểu có tốt đến đâu thì “thực hành tốt” vẫn phải đi trước; ví dụ, để có thể dùng nhất quán và kiểm tra kiểu nghiêm ngặt trong các codebase lớn như Django hay Meta, cần buộc nhà phát triển tuân theo những quy ước được khuyến nghị; Python, giống như C++, có quá nhiều tính năng và runtime quá dễ dãi nên cuối cùng phải chỉ dùng một phần giới hạn thì mới dễ quản lý; nhưng phần giới hạn đó lại có thể khác nhau tùy người và mục đích; cũng so sánh với các trường hợp nhà phát triển Rust va chạm với các nhà phát triển Linux kernel vì hệ thống kiểu nghiêm ngặt hơn
Ở bình luận được upvote cao trong bài Reddit đó có kiểu bác đi rằng “cứ dùng
Anylà xong nên tranh luận vô nghĩa”; nhưng ngay cả trong ví dụ thực tế, nếu có khai báo kiểu rõ ràng hơn thì có thể ngăn lỗi sớm trước các thay đổi tương lai của hàm thư viện hoặc các giá trị đầu vào bất ngờ; khẳng định mạnh rằng nếu muốn mã Python có tính bảo trì và độ tin cậy thì kiểm tra kiểu là bắt buộcKết luận rằng thay vì đổ quá nhiều thời gian và công sức vào kiểm tra kiểu Python, tốt hơn là chuyển hẳn sang một ngôn ngữ static type phù hợp hơn rồi chỉ dùng Python ở những phần cần thiết qua lớp interop; không phải lúc nào cũng làm được, nhưng có nỗi băn khoăn rằng việc cố ép Python cho phù hợp gây lãng phí thời gian rất nhiều
Chỉ trích các tính năng mạnh nhưng phức tạp của Python (ví dụ: meta class, descriptor, dùng
__call__,object.__new__, name mangling,self.__dict__) là chứa quá nhiều “phép thuật”, làm giảm mạnh tính dễ đọc của mã; cá nhân tuyên bố sẽ không dùng các tính năng nàyThắc mắc việc đưa ra ý kiến mà không thực sự dùng ngôn ngữ đó xuất phát từ đâu; các nhà phát triển Python hiểu sâu qua sử dụng thực tế, nên thấy lạ khi người không dùng lại chỉ trích ngôn ngữ bằng cơ sở bên ngoài; chỉ ra bầu không khí tranh luận bằng các contrived example (ví dụ gượng ép)
Với kinh nghiệm dùng Python nhiều năm, khẳng định sai lầm lớn nhất là hoàn toàn không dùng type hint và type checker
Thấy thú vị với “gradual guarantee” của ty, tức là ngay cả khi bỏ đi một annotation kiểu thì cũng không được phát sinh lỗi kiểu; cho rằng đây là cách phù hợp nhất với Python, nơi có rất nhiều mã động
Hồi tưởng rằng kiểu gradual có cấu trúc mà ở đó dù có “any” (kiểu chưa xác định) ở bất kỳ đâu trong mã thì thậm chí cũng không có cảnh báo; từng có vấn đề là ngay cả mã quan trọng cũng không được đảm bảo an toàn kiểu đầy đủ nên không được bảo vệ đúng nghĩa; trong trải nghiệm dùng mypy, đây cũng là điểm chí mạng, và nhất định cần có tính năng khai báo kiểu “file này sẽ được kiểm tra kiểu hoàn toàn tĩnh”; theo ý kiến cá nhân, kiểu “gradual” gần như là một anti-pattern, thậm chí có thể từ “soft typing” còn phù hợp hơn
Quan điểm rằng với codebase hiện có thì ngoài gradual type ra không còn cách nào khác; theo kinh nghiệm thực tế áp dụng type hint cho nhiều codebase Python legacy bằng mypy, “opt-in theo mô-đun” là hợp lý nhất; nếu pyrefly không hỗ trợ điều này thì tính thực dụng sẽ bị giới hạn; tuy vậy, nếu nhìn từ góc độ sinh mã bằng llm (mô hình ngôn ngữ lớn) thì một trình kiểm tra kiểu rất nhanh và nghiêm ngặt vẫn có giá trị
Tương tự giai đoạn đầu áp dụng TypeScript: coi trọng việc onboarding mềm cho các dự án lớn hiện có; dần dần có thể bật các tùy chọn
noImplicitAnyhoặcstricttheo từng mô-đun để cuối cùng chuyển sang môi trường kiểm tra kiểu mạnh mẽNgay cả với tư cách lập trình viên Rust cũng thấy “gradual guarantee” là hợp lý nhất
Nói rằng cá nhân không thấy cách hỗ trợ gradual type hấp dẫn lắm; bản thân hệ thống kiểu động của Python đã bất ổn, nên một nửa mục đích của việc thêm type annotation là để kiềm chế những trục trặc đó; mong muốn nhất định phải có tùy chọn
no-implicit-anyhoặc chế độ strictTooling của Astral đang mang lại năng lượng mới mẻ cho hệ sinh thái Python, nhưng có người đặt nghi vấn về “tầm nhìn dài hạn”: sau này có được tích hợp trực tiếp vào Python không? Có biến mất trong vòng 5 năm không? Có thành một cú rug pull dựa trên thuê bao không?
Thông qua Business Source License, rất có thể Astral sẽ thúc đẩy việc yêu cầu đăng ký doanh nghiệp hoặc tương tự cho các triển khai production dùng công cụ Astral; sản phẩm hiện tại chưa hoàn toàn khớp mục đích đó, nhưng xét từ góc độ đầu tư của venture capital thì có vẻ sẽ đi theo mô hình tương tự
Trong công bố chính thức, Astral nói rõ rằng họ sẽ bán nhiều dịch vụ khác nhau trên nền các công cụ của mình; liên kết tham khảo https://astral.sh/blog/announcing-astral-the-company-behind-ruff
Thực ra nỗi lo này không chỉ áp dụng cho Astral mà cho mọi dự án; đặc biệt cảnh báo rằng tooling của Facebook có rủi ro cao bị “bỏ hoang” theo thời gian; cuối cùng người dùng luôn phải tự gánh rủi ro
Trích ý kiến một người dùng reddit: mô hình cơ bản của VC rốt cuộc là mong được FAANG (big tech) mua lại hoặc phát triển đủ đe dọa để nhắm tới “acqui-hire”; Astral cũng có thể đi theo kịch bản sáp nhập rồi hút nhân tài
Có tin đồn gần đây rằng Astral cũng đang chuẩn bị các công cụ dành riêng cho doanh nghiệp lớn, chẳng hạn private package registry được host sẵn
Với ví dụ “my_list = [1, 2, 3]”, mypy, pyrefly và pyright đều xem
my_list.append("foo")là lỗi kiểu, nhưng chỉ ty cho phép nếu không khai báo gì thêm; có ý kiến cho rằng trong thực tế người ta hầu như luôn dùng list một kiểu duy nhất, nên trình kiểm tra kiểu phải lấy đó làm tiền đề; chỉ trích mạnh rằng không thể vì Python cho phép mà việc kiểm tra kiểu lại trở nên lỏng lẻo; có người hỏi liệu đây có phải chính sách tối ưu cho người mới bắt đầu khôngVới tư cách nhà phát triển ty, giải thích rằng “suy luận kiểu cho list literal vẫn chưa hoàn thiện”; hiện tại chỉ dùng đơn giản
list[Unknown], mà Unknown là kiểu gradual tương tự Any nênappendgì cũng được phép; sau này có kế hoạch suy luận chính xác hơn, và kèm liên kết issue thảo luận https://github.com/astral-sh/ty/issues/168Có ý kiến cho rằng đây không phải tối ưu cho người mới mà là điều không thể tránh khỏi để tương thích với code legacy; nếu muốn đưa type checker vào lượng lớn mã chưa được gắn kiểu thì mã cũ phải tiếp tục chạy gần như nguyên trạng thì gánh nặng mới thấp
Có phản biện rằng “bỏ qua những gì Python cho phép rồi làm tooling theo quan điểm cá nhân thì không thuyết phục”
Chỉ ra vấn đề của cách pyrefly là “khó triển khai toàn diện trong codebase lớn không có kiểu”; vì phải sửa mã từng chỗ nên nếu trong tổ chức không có đồng thuận cho việc này thì sẽ không dễ; ở nơi như Meta, có thể ép nội bộ thì ổn, nhưng nếu nghĩ đến áp dụng dần dần thì cách dễ dãi hơn như ty thực tế hơn; dù vậy, cá nhân lại thích công cụ có thể cảnh báo về kiểu mixed hơn
Có ý kiến rằng “nếu là mã Python có thể chạy được thì mặc nhiên không nên báo lỗi kiểu trừ khi có giới hạn kiểu được khai báo rõ ràng”; nếu muốn một tập con tĩnh nghiêm ngặt hơn thì hãy tự thêm type annotation
Có người từng trải cho rằng cách của Pyrefly theo đuổi suy luận kiểu mạnh hơn, nên trong thực tế với mã lớn cần an toàn kiểu thì số annotation cần viết sẽ ít hơn nhiều; dù khó áp dụng ban đầu nhưng về dài hạn hiệu quả hơn; còn ty thì thực chất giống như đang tắt tùy chọn noImplicitAny
Kỳ vọng có một type checker hỗ trợ tích hợp notebook (live coding) nghiêm túc, để bắt lỗi trước bằng kiểm tra tĩnh trước khi chạy các cell dài sẽ cực kỳ hiệu quả
Hỏi về trải nghiệm dùng Jupyter notebook trong VSCode; có ý kiến rằng áp dụng type checker như pylance đôi khi lại gây cản trở cho mã thử nghiệm
Khuyến nghị trải nghiệm Language Server của VSCode với notebook integration và khả năng phản hồi ngay khi live coding; giải thích rằng nó giải quyết được nhu cầu tích hợp notebook và kiểm tra kiểu tương tác trực tiếp
Thiết kế của Pyrefly tương tự cách suy luận kiểu của TypeScript nên cá nhân thấy hợp lý hơn, và đánh giá việc áp dụng gradual (incemental) theo mô-đun là lý tưởng; nếu đi đến mức theo từng hàm thì quá vụn vặt và thành ra vượt quá nhu cầu; về mặt hiệu năng cũng cho rằng mức mô-đun là đủ
Dù dự án có nhiều tính động thì vẫn nghĩ mình sẽ thích suy luận kiểu mạnh hơn như Pyrefly; dù có bất tiện vì điều đó thì vẫn sẽ nghiêng về phía đó
Hiện tại đang dùng basedpyright trong IDE và môi trường CI, và về cơ bản hài lòng với độ ổn định; không thích mypy vì ngay cả các thao tác kiểu đơn giản đôi khi cũng hay thất bại