3.1 配置文件的三种位置
Ruff 按以下优先级查找配置(命中第一个即停止向上查找):
pyproject.toml里的[tool.ruff]段(推荐,与 PEP 518 生态统一)ruff.toml(独立文件,语法同 pyproject 的 tool.ruff 内容).ruff.toml(以点开头的隐藏版,等价)
Ruff 会从当前目录沿父目录向上查找,直到找到上述任一文件或到达文件系统根。
什么是 pyproject.toml?
pyproject.toml 由 PEP 518 / PEP 621 定义,是 Python 项目的"统一配置总入口"。里面 [project] 放元数据,[build-system] 放构建后端,[tool.xxx] 放各工具的配置。Ruff、Black、pytest、mypy、coverage 都已支持从这里读配置。
3.2 最小可用配置
# pyproject.toml
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]
ignore = ["E501"] # 允许长行(因为已有 formatter 管)
[tool.ruff.format]
quote-style = "double"
3.3 顶层配置项
- line-length(默认 88)
- 最大行宽。Black 默认 88,Google 风格用 80,大型数据科学项目常设 100-120。
- target-version(默认从 project.requires-python 推断)
- 目标 Python 版本,取值
"py38".."py313"。影响 UP 族规则、formatter 的合法语法。 - src(默认
["src"]) - 本地源码目录列表,用于 isort 分组时判定"哪些是本地模块"。
- extend
- 继承另一个 ruff 配置文件(例如团队共享的
/configs/ruff-base.toml)。 - exclude / extend-exclude
- 忽略的路径或 glob 模式。exclude 会覆盖默认值(
.git/.venv/dist等),extend-exclude 则追加。 - respect-gitignore(默认 true)
- 自动跳过 .gitignore 中的文件。
3.4 [tool.ruff.lint]:规则选择
select / extend-select / ignore / extend-ignore 四个是最核心的:
[tool.ruff.lint]
# 启用这些规则族(覆盖默认)
select = ["E", "F", "I", "B", "UP", "SIM", "N"]
# 在 select 基础上再追加
extend-select = ["RUF", "S"]
# 关掉具体规则
ignore = ["E501", "S101"] # 允许 assert(S101)和长行
# 视为可自动修复(safe)——用于收紧/放宽 --fix 行为
fixable = ["ALL"]
unfixable = ["F841"] # 不让 --fix 自动删未使用变量
# 允许 flake8 风格的 # noqa: XXX
external = ["WPS"]
select 还是 extend-select?
团队从 0 搭配置用 select(精确、易审计)。如果基于上游共享配置再加规则,用 extend-select(不破坏继承)。
3.5 per-file-ignores:文件级例外
测试文件里允许 assert、__init__.py 里允许未使用 import 做重新导出——这类需求用 per-file-ignores:
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401", "F403"] # 允许未使用的 import / *
"tests/**/*.py" = ["S101", "D", "ANN"] # 测试里放宽 assert/docstring/注解
"scripts/*.py" = ["T20"] # 脚本允许 print
3.6 [tool.ruff.format]:格式化配置
[tool.ruff.format]
quote-style = "double" # "single" / "double" / "preserve"
indent-style = "space" # "space" / "tab"
skip-magic-trailing-comma = false
line-ending = "auto" # auto/lf/crlf/native
docstring-code-format = true # 对 docstring 里的 ``` 代码块也格式化
docstring-code-line-length = "dynamic"
3.7 [tool.ruff.lint.isort]:import 分组
[tool.ruff.lint.isort]
known-first-party = ["myapp", "mylib"] # 指定哪些包算本地
known-third-party = ["fastapi"]
combine-as-imports = true
force-single-line = false
split-on-trailing-comma = true
section-order = [
"future",
"standard-library",
"third-party",
"first-party",
"local-folder",
]
3.8 [tool.ruff.lint.pydocstyle]
[tool.ruff.lint.pydocstyle]
convention = "google" # "google" / "numpy" / "pep257"
# 选定 convention 后 D 族自动套用合适的子集
3.9 完整示例:FastAPI 项目
[tool.ruff]
line-length = 100
target-version = "py312"
extend-exclude = ["alembic/versions", "generated"]
[tool.ruff.lint]
select = [
"E", "F", "W", # pycodestyle + pyflakes
"I", # isort
"N", # 命名
"UP", # pyupgrade
"B", # bugbear
"C4", # comprehensions
"SIM", # simplify
"PTH", # pathlib 优先于 os.path
"RUF", # Ruff 原创
"S", # 安全
]
ignore = [
"E501", # formatter 管行长
"B008", # FastAPI Depends() 在默认参数是合法用法
]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/**/*.py" = ["S101", "S105", "S106"]
"alembic/env.py" = ["E402"]
[tool.ruff.format]
quote-style = "double"
docstring-code-format = true
3.10 动态查看"生效配置"
配置跨文件继承时容易搞不清"到底用了哪些"。Ruff 提供调试命令:
$ ruff check --show-settings .
# 打印出解析后全部生效配置(JSON 格式)
$ ruff check --verbose .
# 显示每个文件用的是哪份配置
3.11 小结
- 配置写在 pyproject.toml 的
[tool.ruff]段,团队共享。 - 顶层放 line-length / target-version / exclude;
[tool.ruff.lint]放规则;[tool.ruff.format]放格式化;[tool.ruff.lint.isort]放 import 分组。 - select/ignore/per-file-ignores 组合使用,能实现"核心规则全员生效、测试目录放宽"。
- 不确定配置时用
ruff check --show-settings看解析结果。