☰
ruff list --select 使用指南:高效筛选与管理 Python lint 规则
2026/10/6 3:46:18 网站建设 项目流程

你有没有遇到过这种情况:项目里ruff check一直在报某个规则,代码读了半天也不确定它到底归在哪一类,想看看某条规则编号对应的完整说明,又懒得去翻文档。后来我养成了一个习惯:先跑一遍ruff list,再加--select N把规则列表筛到只剩自己想看的那几条。这条命令看起来不起眼,但它才是“手工调教 lint 规则”的第一步。

ruff list --select N里的 N 不是某个神秘参数,它代表你在查询时传入的规则选择器,比如E501、F401、E4这类前缀或完整规则号。很多人把它和ruff check --select N搞混,前者只是“列出并筛选规则目录”,后者才是“在检查时启用哪些规则”。这篇文章我会把 list 命令背后的规则体系讲清楚,再给你几组可以直接抄走的筛选组合,最后聊聊我在实际项目里踩过哪些坑。

1. 先搞懂 list 命令在查什么

1.1 ruff 的规则不是一堆散乱的编号

ruff 的规则体系看起来是“字母+数字”,实际上它是分层级的。拿E501来说,E 是大类,E5 是子类,E501 才是一条具体规则。这种分层不是为了好看,而是为了让使用者可以按“类别”或“子类别”灵活筛选,而不是一次只能选一条规则。

具体到命令行工具里,规则号承担着三重身份:

  • 大类 selector:比如E代表 pycodestyle 的错误类,F代表 Pyflakes 类,W代表警告类。
  • 子类 selector:比如E4代表导入相关(Import),E5代表行长度、空行等风格问题。
  • 完整规则代码:比如E501就是“line too long(行过长)”,F401就是“imported but unused(导入未使用)”。

ruff list默认输出的就是这整棵规则树。你看到的不只是一串代码,每条规则还会带上名字、所属选择器、是否需要 Python 版本、是否支持自动修复等信息。列表很长,所以--select N就是给这份目录做关键词过滤的工具。

如果你只看过ruff check --select,可能会觉得 list 完全是另一个世界。实际上,两者共享同一套选择器语法。理解一套,另一套基本上就通了。

1.2 list 命令解决的三个真实问题

第一个问题是“这条规则到底叫什么”。我只记得项目里报了一个和 unused import 有关的错误,但不确定代码是F401还是其它,这时直接在ruff list --select F的输出里找名字,比打开文档搜更快。

第二个问题是“哪些规则属于这一类”。想把所有“导入相关”的规则一口气看完,就可以ruff list --select E4, I,结果会直接给你分好组,不用挨个猜。

第三个问题是“哪些规则能被自动修复”。虽然ruff check --fix可以一键修,但如果你想在接入前先评估修复范围,直接看 list 输出里的 fix 标记,再结合 JSON 格式二次筛选,效率会高很多。

说白了,list 就是规则目录查询接口,--select N就是缩小目录范围的关键词查询参数。在命令行里做规则治理,这是最顺手的一步。

2. --select N 的筛选逻辑:N 不只是数字

2.1 N 的三种写法:前缀、全码、规则名

--select N里的 N 在 ruff 里叫 selector,它有三种常见写法,很多人只知道第一种。

第一种是大类前缀,比如:

ruff list --select F

这时列出的是F1、F2、F4、F5等所有以 F 开头的子类下全部规则。适合你想看某一个领域内的全部规则,比如 Pyflakes 检查的未定义变量、未使用导入等问题。

第二种是子类前缀,比如:

ruff list --select E4

这时只显示E401、E402这类和导入相关的规则。粒度比大类细,比单条规则粗。实际排查问题的时候,我经常先按子类前缀缩小范围,再定位具体规则号。

第三种是完整规则号或规则名,比如:

ruff list --select E501 ruff list --select line-too-long

两种写法等效。E501是规则号,line-too-long是这条规则的标准名字。规则名的好处是见名知意,适合你不确定编号但清楚想查什么功能的时候用。

这三种写法可以混着传,用逗号分隔即可:

ruff list --select E501, F401, I001

这里要提醒一句:--select的解析是大小写敏感的。E501和e501不是一回事,写错了不会报错,但你会拿到一个空列表,误以为命令没生效。

2.2 多选择器组合时的取并集逻辑

--select传入多个选择器时,规则只要匹配任意一个就会被显示,也就是取并集。举个例子:

ruff list --select F, E4, SIM

输出里可能同时包含 Pyflakes 类、导入错误类、以及 flake8-simplify 的规则。这个设计很符合查目录的习惯:你不想多次执行命令,只想一次性浏览交叉领域。

如果你反过来想“排除一部分规则”,list 命令也支持--ignore参数。比如:

ruff list --select E --ignore E501

这样就是先选出 E 类全部规则,再从中把E501摘掉。说实话,直接--select E4,E5,E7,E8...也不是不行,但写起来又臭又长。能用--ignore表达清楚的事情,就不要手动去拼列表。

还有一个使用细节:当--select和--ignore同时出现时,ruff 会先按--select圈定候选集,再用--ignore剔除。理解这个顺序,排查“为什么少了某条规则”时会省很多力气。

2.3 别和 check 命令的 --select 混在一起

这是新人在命令行里最常踩的坑:ruff list --select E501只是把E501这条规则显示给你看,它不会去扫描代码,更不会修改文件。ruff check --select E501才是真正开启这条规则,并对项目代码执行检查。

打个比方,list 像菜谱目录,check 像真正按菜谱炒菜。你在菜谱里查“红烧肉”不会让厨房里多出一道菜,同样,你在 list 里筛出E501也不会让 lint 开始报行过长。

但这并不意味着 list 的过滤结果没有参考价值。我一般先通过 list 确定规则目录,再把这批规则号整理进pyproject.toml的:

[tool.ruff.lint] select = ["E", "F", "I", "SIM"]

这两个场景是联动的:list 相当于“选品”,check 相当于“执行”。搞清楚了这一层,你就不会在使用时纠结“为什么 list 完之后检查结果没变化”。

3. 在真实项目里实操 list --select

3.1 从大量规则列表里找到一条具体规则

假设你看到 CI 日志里报E501 line too long,你想看看这条规则是否在某个大类下,或者想知道有没有相关变体。打开终端,进入项目管理目录:

ruff list --select E501

输出大致是一个规则目录表,包含规则的 selectors、code、name、是否需要 Python 版本、是否可修复等信息。以本地实际版本为准。如果什么都查不到,先检查一下你输入的规则号有没有写错,或者当前 ruff 版本是否内置这条规则。

想查得更宽一点,比如“所有行长度相关的规则”,可以这样:

ruff list --select E50

E50是子类前缀,比直接只看E501多了上下文的把握。你会发现行长度相关规则可能不止E501,还有注释里的行长度限制等。这个习惯能帮你把“查一条规则”升级成“理解一组规则”。

3.2 按工作场景筛选规则集合

不同的工作场景,我会用不同的选择器组合,这里分享几个常用的:

场景一:新项目想启用“导入排序 + 基础语法”检查:

ruff list --select I, F

先看看这两类规则包含的所有条目,确认没有遗漏后,再把对应的选择器写进配置文件。

场景二:只想关注“代码风格错误”而暂时不管其它:

ruff list --select E --ignore E501, E4

效果是先选 E 大类的全部规则,再剔除行长度、导入布局等容易产生噪音的规则。适合做代码评审时只跑一部分风格检查。

场景三:排查可自动修复的规则:

ruff list --select F --output-format json

用 JSON 格式输出后,再用命令行工具或脚本筛选 fixable 字段为 true 的项。这样可以评估哪些规则能在接入后一键自动处理,省去大量手工修改。

这三种组合的本质,都是把 list 当作“规则归档查询器”使用。你不需要记住所有规则,只需要会查。

3.3 用 JSON 格式做二次筛选与统计

--output-format json是 list 命令容易被忽略的宝藏参数。普通文本格式适合肉眼扫,但如果你想复制粘贴、统计、或者接进脚本流程,JSON 是更好的选择。

简单演示一下,你先执行:

ruff list --select F, E --output-format json > rules.json

然后可以用任意熟悉的工具处理。比如读取 JSON,统计每个大类下可修复的规则数量,或者按是否可修复筛选规则号:

import json with open("rules.json", encoding="utf-8") as f: rules = json.load(f) fixable_rules = [rule["code"] for rule in rules if rule.get("fixable")] print(len(fixable_rules))

实际字段名以你本地的 JSON 输出为准,我见过不同小版本之间字段名会有微调。所以脚本最好在运行时先打印一条记录看看结构。

这个技巧在实际落地时特别好用。比如你想在团队规范里宣布“我们启用了这些规则”,手抄一条条规则号很容易漏,直接跑一个 JSON 筛选再自动生成配置,就不会出错。

3.4 把筛选结果落进项目配置文件

筛选规则最终还是要落到配置里,否则 list 查完就只是信息,不产生规范约束。常见的配置路径是pyproject.toml,示例如下:

[tool.ruff.lint] select = [ "E", # pycodestyle Errors "F", # Pyflakes "I", # isort "SIM", # flake8-simplify ] [tool.ruff.lint.per-file-ignores] "tests/**/*.py" = ["E501"]

在写入配置前,我非常建议先跑一条命令验证你的选择器写法能被 ruff 正确解析:

ruff list --select E, F, I, SIM --output-format text | head -n 20

如果你之前没见过这些名称,先看看列表是否符合预期,再进配置文件。配好之后,跑一次:

ruff check .

确认没有出现“unused rule selector”这类提示。这样 list 和 check 就形成了闭环:目录查询帮助制定配置,配置反哺实际检查。

4. 常见问题与排查技巧实录

4.1 三个最常见的理解偏差

第一个偏差:以为ruff list --select E会修改项目配置。实际它只是查目录,不会写任何文件。你查完规则,还是要自己动手改pyproject.toml或者命令行参数。

第二个偏差:以为 list 会读取当前项目的已启规则,只显示已启用的那部分。实际 list 更多展示的是 ruff 内置规则集中符合你筛选条件的全部规则。查看已启用规则时,应该去看ruff check --show-settings或插件提供的信息。如果发现 list 显示的规则远多于实际启用规则,不要惊讶,这是目录查询的设计。

第三个偏差:以为规则号一定连续、一定存在。实际上E502、E504可能不存在,E509可能也会缺位。规则之间的空号是历史遗留,不代表你的命令出了问题。

如果想让输出干净一点,加上:

ruff list --select E --no-cache

缓存问题少,但我在升级 ruff 后遇到过 list 输出旧规则集的情况,这个参数能强制绕过缓存,排查异常时值得一试。

4.2 参数不生效、输出为空怎么排查

命令查不到规则时,别急着怪工具。按这个顺序排查:

第一步,确认你有没有写对选择器。

ruff list --select E501

和

ruff list --select E051

前者正常,后者大概率为空。看目录时注意规则号前导零,E 类规则常写成 E501 而不是 E0501,两者前缀不同。

第二步,确认当前 ruff 版本是否支持该规则。

ruff --version

再把这个规则号放到官方文档搜索框里查,或者直接打开配置文件看有没有对应的插件依赖。第三方插件提供的规则不会默认内置,没装对应插件时 list 自然搜不到。

第三步,看看是不是大小写问题。

ruff list --select f401

改成:

ruff list --select F401

大小写错误不会报错,但会静默返回空列表。命令行工具有时就是这样,报错比“没结果”更友好。

第四步,检查命令的输出格式是否是 text,避免 JSON 输出打乱你的视觉排查。

4.3 版本差异与第三方插件的影响

ruff 发展很快,规则集也在持续演进。你今天在ruff list里看到的一条规则,在半年后的版本里可能改了名称、被合并成别的规则,或者需要开启 preview 才能查询。

遇到这种情况,我建议先:

ruff list --select RP

看看与 preview 相关的规则是否存在,以及当前版本是否默认展示。有些规则必须在配置中开启 preview 后才出现在 list 里,这是最新几个版本里比较明显的行为变化。

第三方插件方面,比如 flake8-bandit、flake8-bugbear 的类型,ruff 通过内置或配置实现,并不与 flake8 插件共用同一个包名。所以你在 list 里找不到某个 flake8 插件规则时,先确认是否已经通过[tool.ruff.lint] extend-select或插件列表启用了对应来源。

有一个土办法比较直观:直接在项目里跑:

ruff check --select B001 --ignore ALL .

如果 B001 是内置规则,它会参与检查;如果提示无法识别或未启用,那它可能来自某个你还没接入的插件来源。当然,这只是排查思路,真正确认还是要看文档和ruff rule B001的输出。

4.4 常用筛选命令速查表

这里整理一份我自己常放在终端备忘里的对照表,方便你快速查找:

需求命令示例说明
查看某个大类全部规则ruff list --select F列出 Pyflakes 类全部规则
查看子类规则ruff list --select E4只看导入相关规则
查询单条规则详情ruff list --select E501精确显示 E501 一条
查规则名对应的编号ruff list --select line-too-long用规则名反查规则号
多类规则一起看ruff list --select F, I, SIM返回多个选择器并集
先选再剔除ruff list --select E --ignore E501E 类中排除 E501
查看单条规则完整说明ruff rule E501比 list 更详细的文档级输出
以 JSON 格式导出ruff list --select F --output-format json方便脚本或二次统计

表格里多出来的ruff rule E501是我特别想推荐的命令。list 告诉你规则在目录里,rule 告诉你这条规则具体怎么理解、有哪些配置参数、示例是什么样的。两者配合,基本能解决规则调研 80% 的需求。

5. 这条命令在命令行工作流里的位置

如果你和我一样经常在终端里处理多个 Python 项目,ruff list --select N应该被纳入“规则治理”工具箱,而不是把它当成一个偶尔好奇时才摸一下的命令。

我的习惯是:新接一个仓库,先跑ruff list --select F, E, I看看现有规则覆盖面;遇到 CI 报错,先跑ruff rule 规则号理解报错意图;要调整规范时,再跑ruff list --select 选择器验证哪些规则会进入配置。这样一来,命令行就不只是“跑检查”的地方,而是变成了一个可以自由查询规则目录的交互环境。

你会慢慢发现,几乎所有 lint 规则问题都可以转化为“选择器 + 查询 + 验证”三步。选择器负责缩小范围,list 命令负责展示结构,ruff check负责最终验证。三步走完,规则配置基本不会跑偏。

最后分享一个小技巧:如果你经常要在不同项目里对比规则集,可以先把当前项目的规则列表导出成文件:

ruff list --select E, F, I, SIM --output-format json > rules-backup.json

之后再升级 ruff 或调整依赖,直接 diff 这个文件,就能清楚看到规则集发生了哪些变化。这个方法比肉眼翻文档靠谱得多,也适合在团队里做规则变更记录。命令行工具的乐趣,就在于这些细微但扎实的效率提升。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询