幾天前,Python 開源社群又出了一個不小的新聞:HTTPX 和 Starlette 在同一天將在用的程式碼分析工具(flake8、autoflake 和 isort)統一替換成了 Ruff。
HTTPX 是一個支援非同步的 HTTP 客戶端,Starlette 是一個輕量級的 ASGI 框架,它們都是 Python 社群裡的明星專案,目前加起來有近 20K star。它們都選擇了使用 Ruff,再次擴大了 Ruff 的應用版圖。
Ruff 是個誕生僅僅 8 個月的新興專案,但已呈現出一種席捲 Python 社群的趨勢!很多知名的開源專案已採納 Ruff,比如 Transformers、Pandas、FastAPI、Airflow、SciPy、Bokeh、Jupyter、LangChain、PaddlePaddle、Sphinx、Pydantic、LlamaIndex……
Ruff 是什麼?為什麼它能吸引大量的開源專案使用?相比於其它程式碼分析工具,它有哪些突出之處,是否還有一些侷限性?現在是否值得將專案在用的工具都替換成它呢?
帶著這些問題,本文將帶你全方位瞭解這個火爆的專案。
Ruff 加速 Rust 與 Python 的融合
Ruff 誕生於 2022 年 8 月,它是一個用 Rust 語言編寫的高效能的 Python 靜態程式碼分析工具,比其它分析工具快幾個數量級(10-100 倍),而且功能也很全面。
程式碼分析工具
即 Linter,用於檢查程式碼中的語法錯誤、編碼規範問題、潛在的邏輯問題和程式碼質量問題等,可以提供實時反饋和自動修復建議。
在 Ruff 出現之前,社群裡的程式碼分析工具呈現出百花齊放之勢,比如有 Pylint、Flake8、Autoflake、Pyflakes、Pycodestyle 等等,它們的共同點是都使用 Python 編寫而成。
Ruff 異軍突起,在效能方面立於不敗之地,主要得益於 Rust 天然的速度優勢。Ruff 的出現,就像基於大語言模型的 ChatGPT 橫空出世,所有競爭對手瞬間就黯淡失色了。
兩個月前,我翻譯了一篇《Python 2023 年的 3 個趨勢》,它預測的第一個趨勢就是 Rust 將加快融入到 Python 相關的專案和工具中,舉出的例子就有 Ruff。
我現在可以補充一個觀察了:用 Rust 開發的新工具將淘汰用其它語言開發的工具,而且新工具的普及速度可能比你的預想快得多!
Ruff 專案的成功,將刺激出更多 Python+Rust 的專案。它的作者 Charlie Marsh 立志於給 Python 構建高效能的開發工具,巧合的是我曾翻譯過他寫的《Using Mypy in production at Spring》,這篇文章恰好釋出於 Ruff 誕生的 2022 年 8 月!
因此,我有理由推測:在 Ruff 專案成熟後,他將用 Rust 開發高效能的 Python 型別檢查工具,到時候,目前流行的 Mypy、Pytype、Pyright 和 Pyre 等工具將迎來一大勁敵。(題外話:Python 社群紛亂繁多的虛擬環境管理工具和依賴包管理工具,也有望迎來變革了吧!)
這裡還必須介紹兩個 Rust 專案,因為 Ruff 的成功離不開它們:
- RustPython :用 Rust 寫成的 Python 直譯器。Ruff 利用了它高效能的 AST 解析器,以此實現了自己的 AST 遍歷、訪問器抽象和程式碼質量檢測邏輯
- Maturin :用 Rust 寫成的打包工具,可以將 Rust 專案打包成 Python 可用的包,從而可以被我們“pip install”後使用,且不需要配置 Rust 環境
Ruff 的優點與侷限性
介紹完最關鍵的特性後(速度極快、支援 pip),我們接下來看看 Ruff 的其它方面。
總體而言,它具有這些特點:
- 支援
pyproject.toml
- 相容 Python 3.11
- 超過 500 條內建規則,與 Flake8 內建的規則集近乎對等
- 重新實現了數十個 Flake8 外掛,如 flake8-bugbear、flake8-comprehensions 等
- 支援自動修復,可自動糾正錯誤(例如,刪除未使用的匯入)
- 內建快取,可避免重複分析未更改的檔案
- 支援 VS Code、Pycharm、Neovim、Sublime Text、Emacs 等編輯器
- 對 monorepo 友好,具有分層和級聯配置
首先最值得介紹的是它支援的規則。Ruff 借鑑了流行的工具如 Flake8、autoflake、isort、pyupgrade、yesqa 等等,然後用 Rust 重新實現了超過 500 條規則。它本身不支援外掛,但是吸收了數十個常用的 Flake8 外掛的設計,使得已囊括的規則範圍比其它任何工具都大。
Ruff 的作者還非常熟悉其它語言的分析工具,比如 Rust 的 Clippy 和 JavaScript 的 ESLint,並從這些專案上得到了設計上的啟發。
Ruff 站在了多個工具/外掛的肩膀上,重新實現了它們驗證過的規則,也借鑑了它們的 API 和實現細節,這使得它扮演了一種“集大成”的角色,很方便使用者們作工具的順滑遷移。
Ruff 第二個值得介紹的特點是,它沒有侷限於 Linter 的定位,而是借鑑 Rome、Prettier 和 Black 這些程式碼格式化工具(Formatter),也實現了程式碼格式化的功能。借鑑了 Autoflake、ESLint、Fixit 等工具,實現了程式碼自動糾錯的功能。另外,它還借鑑了使用很廣泛的 isort,支援對 import 作快速排序。
這些表明作者的目標並不只是開發一款優秀的程式碼分析工具,而是在靜態程式碼分析的核心功能外,要創造出更多的可能性。此舉是開發者的福音啊,以後一個工具就能滿足多種訴求,再也不必糾結於不同工具的選型、協作與維護了!
Ruff 還有其它的優點,例如支援 pyproject.toml
、支援 Python 3.11、支援只分析變更的檔案,等等。另外,它也有著一些侷限性:
- 支援的 lint 規則還有不夠
- 不支援使用外掛,擴充套件性不強
- 用 Rust 開發的,因此不便於在出錯時 debug,也不便於 Python 開發者給它貢獻程式碼
關於第一點,畢竟 Ruff 只是 8 個月大的新生專案,支援更多的規則,只是時間問題。至於外掛帶來的擴充套件性和程式語言的開發者生態,原因也是 Rust,屬於“有得必有失”了。
Ruff 的使用
介紹完 Ruff 的整體情況後,我們接著看看該如何使用它吧。
首先是安裝,可以用 Conda 和其它包管理工具,也可以直接用 pip:
pip install ruff
可以透過以下命令執行:
ruff check . # 分析當前及子目錄內的所有檔案
ruff check path/to/code/ # 分析指定目錄及子目錄內的所有檔案
ruff check path/to/code/*.py # 分析指定目錄內的所有py檔案
ruff check path/to/code/to/file.py # 分析 file.py
可以用作預提交的鉤子:
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: 'v0.0.261'
hooks:
- id: ruff
可以透過 pyproject.toml
,ruff.toml
或 .ruff.toml
檔案進行配置,預設配置已能滿足基本使用,詳細配置可以參見文件的 Configuration 。
Ruff 提供了官方的 VS Code 外掛,可以快速上手:
Ruff 官方沒有提供 Pycharm 的外掛,社群中有人釋出了一個 Ruff 外掛。
另外,它還提供了ruff-lsp
,可以被整合到任何支援 Language Server Protocol 的編輯器中,例如 Neovim、Sublime Text、Emacs 等等。
小結
本文從 HTTPX 和 Starlette 採納 Ruff 的新聞開始,向讀者介紹了這個僅誕生 8 個月卻俘獲了一大批知名開源專案。它最突出的特點是使用 Rust 開發,因此在效能方面遠遠超越同類工具,此外,它借鑑了眾多工具和外掛的設計,不僅靜態程式碼分析的規則全面,而且還具備程式碼格式化、程式碼自動糾錯和 import 排序等非其它 linter 所擁有的功能。
Ruff 的成功為 Python 社群提供了一個鮮活的榜樣,可以預見,我們將迎來一波用 Rust 開發的高效能工具。Ruff 的成功,與最近火爆的 ChatGPT 一樣,它們傳遞出了一個“這事兒能成”的訊號,從而會引爆一場使用新技術的變革!(非常巧合的是:Rust 1.0 在 2015 年 5 月釋出,而 OpenAI 在 2015 年 12 月成立。)
總體而言,Ruff 非常強大,憑實力而風靡 Python 社群,絕對推薦使用!它的使用文件很友好,如果你想了解更多細節,可以去翻查。