Ruff 是 Astral 用 Rust 寫的 Python linter 與 formatter,速度比 Flake8、Black 快 10-100 倍,用一個指令就能取代 Flake8(加幾十個外掛)、isort、Black、pyupgrade、autoflake 這整套 Python 程式碼品質工具鏈。截至 2026 年 8 月,Ruff 在 GitHub 已累積 49,000+ 星,FastAPI、Hugging Face、Pandas、Apache Airflow、PyTorch 等知名專案都在用它。
一句話結論
Ruff = Python 開發者的「一條龍程式碼品質工具」:ruff check 做靜態檢查(找出未使用的 import、潛在 bug、資安風險),ruff format 做自動排版,兩者都是毫秒級完成。它用 Rust 重寫了 Flake8 生態系的 900+ 條規則,內建快取與自動修復(--fix),設定全寫在 pyproject.toml 裡,是 2026 年 Python 專案最值得第一個安裝的開發工具。
為什麼 2026 的 Python 開發者都在用 Ruff?
傳統 Python 專案的程式碼品質工具鏈是這樣的:Flake8 檢查風格、Black 排版、isort 排 import、pyupgrade 升級語法、autoflake 刪冗餘程式碼——五個工具、五套設定、五倍等待時間。Ruff 把這五件事(還有更多)合併成一個二進位檔:
- ⚡ 快 10-100 倍:Dagster 共同創辦人 Nick Schrock 實測:pylint 掃 25 萬行的 dagster 程式庫要 2.5 分鐘,Ruff 掃整個 codebase 只要 0.4 秒
- 📦 內建快取:不會重複分析沒改動的檔案,愈掃愈快
- 🔧 自動修復:
ruff check --fix自動刪未使用的 import、自動加未來註解,不用動手 - 📏 900+ 條規則:原生用 Rust 重寫 Flake8 熱門外掛(bugbear、bandit 資安規則、pytest-style 等)
- 🤝 Drop-in 相容:跟 Flake8、isort、Black 的既有規則相容,遷移成本極低
- 🌎 Monorepo 友善:支援階層式設定,每個子專案可以覆蓋父層設定
安裝 Ruff(5 種方式任選)
Ruff 目前最新版為 0.16.4,支援 Python 3.14。如果你已經在用 uv(Astral 的另一個明星專案),直接一行搞定:
# ✅ 推薦:用 uv 全域安裝
uv tool install ruff@latest
# 或當成專案的開發依賴
uv add --dev ruff
# 傳統方式
pip install ruff
pipx install ruff
# 獨立安裝器(macOS / Linux)
curl -LsSf https://astral.sh/ruff/install.sh | sh
# macOS 也可以用 Homebrew
brew install ruff
不想安裝的話,還能用 uvx ruff@0.16.4 check 直接跑,用完即丟。
第一個指令:check 與 format
安裝完立刻就能用,零設定:
# 靜態檢查目前目錄(含子目錄)的所有 .py 檔
ruff check
# 自動修復所有能自動修的問題(例如刪未使用的 import)
ruff check --fix
# 只檢查某個檔案或資料夾
ruff check src/ app/main.py
# 自動排版(等價於 Black 的格式規範)
ruff format
# 排完版再檢查一遍(常用組合)
ruff check --fix && ruff format
Ruff 0.16 的預設規則集就涵蓋了 40+ 個規則類別(含 flake8-bugbear 的 B、bandit 的 S 資安規則、pyupgrade 的 UP、isort 的 I 排序),也就是說你什麼都不設定,它已經能抓出一堆常見問題——最典型的就是「未使用的 import」。
pyproject.toml 完整設定實戰
Ruff 的設定寫在 pyproject.toml(或獨立的 ruff.toml / .ruff.toml),用 [tool.ruff] 前綴。這是一份適合中型專案的實用設定:
[tool.ruff]
# 一行最多 88 字元(跟 Black 預設一致)
line-length = 88
# 假設專案最低支援 Python 3.10
target-version = "py310"
[tool.ruff.lint]
# 明確啟用規則類別:E=pycodestyle 錯誤、F=pyflakes、
# I=isort 排序、UP=pyupgrade、B=bugbear、SIM=簡化、S=bandit 資安
select = ["E", "F", "I", "UP", "B", "SIM", "S", "RUF"]
# 忽略特定規則(例如允許 print 除錯)
ignore = ["S101"] # assert 用於測試沒關係
# 某些檔案放寬規則(例如 __init__.py 允許未使用的 import)
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
[tool.ruff.format]
# 跟 Black 一致:雙引號、空格縮排
quote-style = "double"
indent-style = "space"
規則代碼速查表
Ruff 的規則代碼沿用 Flake8 生態的命名,看到代碼就知道是哪一類:
| 代碼 | 來源 | 檢查什麼 | 範例 |
|---|---|---|---|
F | Pyflakes | 未使用的 import、未定義變數 | F401 未使用 import |
E / W | pycodestyle | PEP 8 風格錯誤 / 警告 | E501 行太長 |
I | isort | import 排序 | I001 import 未排序 |
UP | pyupgrade | 升級到新版 Python 語法 | UP038 改用 X | Y 型別 |
B | flake8-bugbear | 常見潛在 bug | B006 可變預設參數 |
SIM | flake8-simplify | 程式碼簡化 | SIM108 改用三元運算子 |
S | flake8-bandit | 資安風險 | S101 使用 assert |
N | pep8-naming | 命名慣例 | N802 函式名稱大小寫 |
C4 | flake8-comprehensions | 改用 comprehensions | C400 不必要的 list() |
ANN | flake8-annotations | 型別註解完整性 | ANN201 缺回傳型別 |
T20 | flake8-print | 偵測 print | T201 程式碼裡有 print |
RUF | Ruff 專屬 | Ruff 自己的規則 | RUF001 混淆字元 |
從 Flake8 + Black + isort 遷移過來
舊工具用戶不用擔心:Ruff 就是設計來當 drop-in 替代品的。比較如下:
| 項目 | Flake8 + Black + isort + pyupgrade | Ruff |
|---|---|---|
| 工具數量 | 4+ 個(各配一套設定) | 1 個 |
| 掃描 25 萬行程式碼 | 分鐘級 | 0.4 秒 |
| 自動修復 | 部分(autoflake 等) | ✅ --fix 內建 |
| 設定檔 | 分散多檔 | 統一 pyproject.toml |
| 資安規則(bandit) | 需另外裝外掛 | ✅ 內建 S 類別 |
| 型別註解檢查(ANN) | 需另外裝外掛 | ✅ 內建 |
| 快取 | ❌ | ✅ 內建 |
遷移三步驟:① pip uninstall flake8 black isort pyupgrade autoflake ② 安裝 Ruff ③ 把 .flake8、black.toml、isort.cfg 的設定合併進 pyproject.toml 的 [tool.ruff]。格式部分,Ruff 的 formatter 就是「Black 相容」的(兩者都基於 88 字元、雙引號、magic trailing comma 原則),排版結果幾乎一致。
pre-commit 整合(在地 commit 前就把關)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.4
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format
這樣每次 git commit 都會先跑 lint+排版,不合格的檔案自動被擋下或修好,壞程式碼進不了 git 歷史。
GitHub Actions CI(遠端也把關)
# .github/workflows/ruff.yml
name: Ruff
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v3
官方 ruff-action 會自動安裝最新版 Ruff 並執行 ruff check,任何違反規則的 PR 都會被紅燈擋下。
VS Code 整合
安裝官方擴充套件 Ruff(由 Astral 維護),即可獲得:
- 輸入時即時顯示 lint 錯誤(紅色波浪線)
Shift+Alt+F直接格式化- 儲存時自動修復(
editor.codeActionsOnSave設定) - 內建 Ruff Language Server(
ruff server),比舊版ruff-lsp更快
// .vscode/settings.json
{
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit"
}
}
}
進階技巧
- Preview 模式:
[tool.ruff.lint] preview = true(或ruff check --preview)可搶先啟用尚未穩定的新規則。 - Monorepo 階層設定:根目錄放一份設定,子專案用各自的
ruff.toml覆蓋部分規則,Ruff 會自動級聯套用。 - 只看差異:
ruff check --diff預覽修改內容;--statistics統計各規則觸發次數。 - 與型別檢查器分工:Ruff 管「風格與明顯 bug」,型別檢查交給 Ty 或 mypy——兩者不衝突,可以一起用。
flowchart LR
A[寫程式] --> B[ruff check<br/>靜態檢查 + --fix 自動修復]
B --> C[ruff format<br/>自動排版]
C --> D{pre-commit<br/>檢查是否通過}
D -->|通過| E[git commit]
D -->|不通過| A
E --> F[GitHub Actions<br/>ruff-action 再驗一次]
F -->|通過| G[CI 綠燈 ✅]實戰:把一包「髒程式碼」交給 Ruff
假設你接手一個別人寫的爛專案,檔案長這樣:
import os
import json
from datetime import datetime
def get_user_data(user_id):
# fetch user data from db
data = fetch_from_db(user_id)
if data == None:
return {}
else:
result = dict()
for key in data.keys():
result[key] = data[key]
return result
def save_report(rows):
f = open("report.csv", "w")
f.write("id,name\n")
for row in rows:
f.write(f"{row['id']},{row['name']}\n")
f.close()
執行 ruff check .,Ruff 一口氣抓到這些問題:
app.py:1:8: F401 [*] `os` imported but unused
app.py:3:1: I001 [*] Import block is unformatted
app.py:8:12: E711 Comparison to `None` should be `cond is None`
app.py:10:9: SIM108 [*] Use a ternary operator instead of if-else
app.py:11:16: C416 [*] Unnecessary `dict` comprehension
app.py:16:9: SIM115 Use a context manager for opening files
app.py:16:14: S108 [*] Probable insecure usage of temporary file
接著下 ruff check --fix && ruff format,幾毫秒內全部自動修好:未使用的 os 被刪掉、import 排好序、== None 改成 is None、if-else 變三元運算子、dict comprehension 簡化。剩下 SIM115(建議改用 with open(...))這種需要人工判斷的,Ruff 會留著提醒你,不會亂改你的邏輯。
這就是 Ruff 的日常:機械性問題它全包,需要判斷力的留給人類工程師。
誰在用 Ruff?
Ruff 的採用名單幾乎是 Python 界的「全明星隊」:FastAPI、Hugging Face(Transformers/Datasets/Diffusers)、Pandas、SciPy、Apache Airflow、Apache Superset、PyTorch、JAX、pytest、Streamlit、LangChain、LlamaIndex、Gradio、Home Assistant、Netflix Dispatch、Microsoft Semantic Kernel……連 Poetry、Pylint、Mypy 這些「被取代的對象」自己都在用 Ruff 檢查自己的程式碼。如果你的專案還沒有 Ruff,加入他們只是時間問題。
常見問題
Q:Ruff 跟 Black 排版會打架嗎? 不會。Ruff 的 formatter 就是相容 Black 的設計(同為 88 字元、雙引號、magic trailing comma),大部分專案可直接替換。極少數邊界案例可參考官方 FAQ 的差異清單。
Q:Ruff 能取代 mypy 嗎?
不能。Ruff 不做型別推斷,型別檢查請交給 Ty / mypy。Ruff 的 ANN 規則可以「要求」你寫型別註解,但真正驗證型別是另一回事。
Q:團隊不想用 Black 風格怎麼辦?
Ruff 支援設定 quote-style = "single"、line-length 等參數調整排版風格,也可以只關掉 formatter、只用 linter(ruff check 單獨存在)。
Q:Ruff 快是真的假的? 真的。Bokeh 共同創辦人、Conda 原作者 Bryan Van de Ven 實測:「Ruff 比 flake8 快約 150-200 倍,掃整個 repo 約 0.2 秒(原本約 20 秒),快到我把牠直接掛成 commit hook。」
延伸閱讀
- uv:Astral 的全能 Python 套件與專案管理器 — Ruff 的兄弟專案,Rust 寫的 pip/poetry/pyenv 終結者
- Ty:Astral 用 Rust 寫的極速 Python 型別檢查器 — 跟 Ruff 組成「Astral 三兄弟」,型別檢查交給它
- FastAPI 完整教學 2026:從安裝、路由、Pydantic v2 到依賴注入與部署 — FastAPI 官方就是用 Ruff 的專案之一
