如果你一直在用 Ruff,肯定遇到过 ruff list --select N 这种命令。我第一次看到时也愣了一下:list 不是 Python 里的内置类型吗,怎么 Ruff 也有一个 list?后来翻文档才明白,这是 Ruff 提供的规则查询命令,--select N 则是一个过滤器,专门让我们查看 pep8-naming 插件下的那批命名规范规则。对刚接触 Ruff 的人来说,这条命令真的值得花几分钟吃透,因为它能帮你快速搞清楚 N 规则族到底管什么,也能让你在写配置文件时不再靠猜。
这篇文章我会从命令拆解讲起,配合实际输出、常见参数、配置方法和踩坑记录,把 ruff list --select N 的语法和背后逻辑一次讲透。不管你是刚开始用 Ruff,还是已经跑过一阵子但没仔细研究过规则列表,这篇内容都能对你有用。
1. 认识 ruff list --select N 这条命令
1.1 拆解命令:list 要做什么,--select N 过滤什么
先把命令拆开看。ruff list 是 Ruff 提供的一个子命令,作用是列出当前 Ruff 已知的所有可检查规则。它不会去检查你的代码,它做的事更接近“查字典”——把规则仓库里的规则条目打出来给你看。
--select N 是 list 的过滤参数,含义是“只要规则代码匹配 N 前缀的规则”。这里的 N 不是 numpy 的 N,也不是 node 的 N,而是 Ruff 里一个规则分类前缀,对应 pep8-naming 这一组命名规范规则。所以 ruff list --select N 合起来的意思就是:列出当前版本 Ruff 中,所有归属于 pep8-naming 的规则。
这个设计思路和 ruff check --select N 很像,但用途不一样。ruff check --select N 是告诉检查器“按这批规则去检查代码”,而 ruff list --select N 是“把这批规则条目展示出来”。一个是执行检查,一个是查看规则库,别混在一起用。
1.2 为什么需要一条规则查询命令
很多 Python 开发者一开始用的是 Flake8,规则由插件扩展,想知道某个插件有哪些规则,得上网查文档,或者看插件的 README。Ruff 把这种“查规则”的体验搬进终端,好处很明显:你不用开着浏览器去翻 GitHub,也不用记官方文档的目录,一条命令就能确认当前安装的 Ruff 到底支持哪些规则。
而且 Ruff 版本更新很快,规则也在不断调整。你两个月前记的规则编号,可能在升级后发生了变化,也可能新增了别的规则。靠记忆去写 select 配置,很容易出错。用 ruff list --select N 直接看当前版本的规则清单,永远是最可靠的信息源。
还有一个场景也很实用:在做团队规则梳理时,你可能需要确认某个规则前缀下面到底有多少条规则,每条规则的核心消息是什么。这时候把列表输出结果复制到文档里,就是一份现成的规则台账,比手动维护省心得多。
1.3 运行效果:你会看到什么样的输出
在较新版本的 Ruff 里运行 ruff list --select N,输出大致长这样:
bash复制$ ruff list --select N
N801 invalid-class-name Class names should use CapWords convention
N802 invalid-function-name Function name should be lowercase
N803 invalid-argument-name Argument name should be lowercase
N804 invalid-first-arg-name-cls First argument of a classmethod should be named cls
N805 invalid-first-arg-name-self First argument of a method should be named self
...
每行通常包含三部分:规则代码、规则名称、规则的简短说明。你不需要死记这些编号,但看到这个输出后,至少能明白 N 这一族规则大概在管什么事情——它管的是 Python 代码里各种标识符的命名格式,比如类名要怎么写、函数名要怎么写、方法的第一个参数叫什么。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. ruff list --select N 的完整语法与参数解析
2.1 --select 参数到底怎么传
--select 后面跟的是规则选择器,最简单的传法就是前缀字母,比如 N、E、F、W。这些字母对应 Ruff 内置的不同规则分类:E 是 pycodestyle 的 error,W 是 pycodestyle 的 warning,F 是 pyflakes 的规则,N 就是 pep8-naming。
除了传前缀,你还可以传完整的规则编号,比如:
bash复制ruff list --select N802
这样只会显示 N802 这一条规则。如果你想把几条规则放在一起看,用逗号分隔就行:
bash复制ruff list --select N802,N803
也可以写多个 --select:
bash复制ruff list --select N --select E4
注意,多个 --select 和逗号分隔是同一个效果,都表示“取并集”。Ruff 对这类规则参数的解析逻辑比较统一,只要你之前配过 select = ["N", "E4"],那么在命令行里传 --select N,E4 或 --select N --select E4 都是符合直觉的。
2.2 常见搭配:--ignore、--output-format、--all
ruff list 不只支持 --select,它还有几个和规则查询关系很大的参数。我这里挑三个实际用得上的场景来说。
第一个是 --ignore,它和 --select 正好相反,用来排除匹配到的规则。比如你想列出所有 N 开头的规则,但暂时不想看到 N802,可以这么写:
bash复制ruff list --select N --ignore N802
这个组合在做“哪些规则我没启用”的时候很好用。配合 --select ALL,你可以把当前 Ruff 已知的全部规则列出来,再排除掉某一类:
bash复制ruff list --select ALL --ignore F
第二个是 --output-format,可选值通常有 text、json、grouped。默认是 text,人眼看着舒服。如果你要写脚本解析规则列表,建议直接输出 JSON:
bash复制ruff list --select N --output-format json
JSON 输出包含规则代码、名称、消息、文档地址、修复可用性等信息,结构稳定,适合进一步处理。grouped 格式会按规则类别分组展示,适合想快速扫一眼大类构成的情况。
第三个是 --all。这个参数的含义是“把规则列表里的所有规则都展示出来,包括某些默认没有启用的规则”。Ruff 有不少规则在默认配置下是不开启的,直接跑 ruff list 可能看不到完整集合,加上 --all 才能看到全量清单。如果你想彻底搞清楚一个前缀下到底有多少候选规则,--all 别漏掉。
2.3 参数规则速查表
为了方便查阅,我把几个关键参数整理成了一张表:
| 参数 | 作用 | 示例 |
|---|---|---|
--select <RULES> |
只显示匹配指定前缀或规则代码的规则 | ruff list --select N |
--ignore <RULES> |
排除匹配指定前缀或规则代码的规则 | ruff list --select ALL --ignore F |
--all |
显示包括默认未启用的全部规则 | ruff list --select N --all |
--output-format <FORMAT> |
指定输出格式,支持 text/json/grouped | ruff list --select N -o json |
-h, --help |
查看帮助信息 | ruff list --help |
建议养成一个好习惯:拿到新版本 Ruff,先跑一次 ruff list --help,把当前版本的参数看一遍。因为命令行工具在迭代时偶尔会调整参数名,不同版本的 --select 和 --ignore 行为可能有细微差别,以你本机实际帮助文档为准最稳妥。
3. 从查询规则到落地配置:N 规则族的实操流程
3.1 安装与查询:先跑通命令
如果你还没安装 Ruff,可以先按官方方式装一下。最常见的安装方法是 pip 或 cargo:
bash复制pip install ruff
装完确认版本:
bash复制ruff --version
然后就可以跑查询命令了:
bash复制ruff list --select N
如果命令提示找不到 list 参数,说明你的 Ruff 版本比较旧。这种情况建议先升级:
bash复制pip install --upgrade ruff
在我个人经验里,Ruff 的老版本规则查询能力是合并在 ruff rule 里的,后来才把 list 独立出来。升级到较新版本后,使用体验会统一很多。
3.2 理解 N 规则族:命名规范的前世今生
N 前缀的规则来源于 pep8-naming,一个老牌的 Flake8 插件。它的目的很简单:检查代码里的命名风格是否符合 PEP 8 的约定。Ruff 把这一整套规则内置了进来,所以你在 ruff list --select N 里看到的规则,在语义上基本能在 pep8-naming 插件里找到对应。
这套规则覆盖的场景很广:
- 类名是不是使用了
CapWords风格; - 函数名是不是用了
snake_case; - 参数名是不是用了
snake_case; - 类方法第一个参数是不是
self; - 类方法(
classmethod)第一个参数是不是cls; - 变量名、常量名、导入名的命名风格是否一致;
- 异常类的类名是否以
Error结尾。
看到这里你可能会觉得,这不就是“强制小写加下划线”吗?其实没那么简单。PEP 8 对不同类型的标识符有不同的推荐风格,N 规则就是把这些推荐风格变成可自动检查的硬性条款。它比很多团队手写的命名规范更具体,也更容易执行。
3.3 把 select = ["N"] 写进项目配置
知道有哪些规则之后,下一步就是把规则落到项目配置里。Ruff 使用 pyproject.toml 作为配置文件,在 [tool.ruff.lint] 字段下设置 select。
如果你想启用整个 N 规则族,在 pyproject.toml 里写:
toml复制[tool.ruff.lint]
select = ["N"]
这样 Ruff 做 ruff check 时,就会按 pep8-naming 的规则检查你的代码。如果项目里已经有别的规则,可以把 N 和其他前缀一起写:
toml复制[tool.ruff.lint]
select = ["E", "F", "W", "N"]
这里有一个容易忽略的细节:select 列表里的规则和 ignore 列表里的规则是配合工作的。如果你在 select 里写了 N,又在 ignore 里写了 N802,那么 N802 会被排除。实际使用中,我建议把 select 看作“大类开关”,把 ignore 看作“单点例外”,这样配置最清晰。
3.4 按需微调:用 ignore 和逐个规则配置
很多项目不会无脑启用所有 N 规则,因为有些规则在当前代码库下可能太严格。这时候就要先通过 ruff list --select N 看清楚有哪些可选项,再结合项目现状做取舍。
比如你查出来后,发现 N806(函数里的变量名不是小写风格)这条规则和你团队现有的命名习惯冲突,那就可以在 ignore 里排除它:
toml复制[tool.ruff.lint]
select = ["N"]
ignore = ["N806"]
如果你觉得整组 N 规则没问题,但不确定某条规则具体检查什么,可以先看这条规则的完整文档:
bash复制ruff rule N806
ruff rule 会输出规则的详细介绍,包括适用场景、错误代码、示例和修复建议。先把规则读明白再决定要不要启用,比盲目 select = ["N"] 要靠谱得多。
4. N 规则族的实用细节与常见误区
4.1 N 系列规则覆盖的命名场景
N 规则族不是只有“函数名要小写”这么简单,它其实覆盖了 Python 命名体系的多个层次。这里我按代码位置拆一下:
- 类名:N801 检查类名是否使用 CapWords,异常类名还有额外的 N818 检查,要求后缀带
Error。 - 函数和方法:N802 检查普通函数名是否小写,N803 检查参数名是否小写,N804 和 N805 分别检查类方法的第一个参数是不是
cls/self。 - 变量:N806 检查函数内变量名风格,N815 和 N816 则分别检查类作用域和全局作用域的变量是否出现 MixedCase。
- 导入:N811、N812、N813、N814、N817 会检查导入名称与原始名称的风格是否匹配,防止导入时把命名风格改得面目全非。
不同规则的细节很多,但核心思想一致:代码里每一个标识符,都要尽量遵循 PEP 8 对不同上下文的命名约定。这套体系在团队协作中非常有用,因为命名风格统一后,代码的阅读成本会明显下降。
4.2 容易踩的误区:N 不是 NumPy 也不是 Node
我第一次见到 --select N 时,第一反应是“N 是哪个新插件?是不是和 NumPy 有关?”后来查了文档才发现,这个 N 在 Ruff 里固定代表 pep8-naming 规则族。它不是某个库的缩写,也不是 NumPy 风格检查,就是命名规范。
还有一个容易踩的坑是:ruff list --select N 只是列出规则,并不会对当前项目做检查。有些新手会拿它去“验证”某个代码文件的命名是否符合规范,结果发现没输出,以为是代码没问题。其实这个命令的输出是“有哪些规则”,而不是“哪些代码违反了规则”。想检查代码,要跑的是:
bash复制ruff check .
这两个命令一个查规则库,一个查代码文件,千万别混。
4.3 和 flake8-pep8-naming 的差异
如果你之前用过 Flake8 加 flake8-pep8-naming 插件,可能会觉得 Ruff 的 N 规则就是照搬。整体上确实如此,但两者在规则编号和细节上不完全一致。Ruff 内置的 N 规则在消息文本上做过重新整理,部分规则编号和原插件的编号对应关系也有一点调整。
这带来的实际问题是:从 Flake8 迁移到 Ruff 时,不能完全照搬原来配置文件里的规则编号。最好的做法是在 Ruff 里跑一遍 ruff list --select N,以当前版本的输出为准重新映射。不要看一眼网上旧的规则编号就抄进 pyproject.toml,很可能会失效。
5. 常见问题与排查技巧实录
5.1 为什么命令输出为空
如果你运行 ruff list --select N 后什么都没打印,先别急着怀疑命令写错了,按下面顺序排查。
第一,确认 Ruff 版本足够新。老版本可能没有 list 子命令,或者 --select 行为不完整,升级到最新版再试。第二,确认你传的规则前缀是真实的。Ruff 的规则前缀和插件代码对应,不是随便一个字母都有效。如果传了不存在的 X,自然查不到规则。第三,确认没有意外加了 --ignore 之类的参数把结果过滤掉了。我出现过一次在长命令里漏看了 --ignore N,结果列表为空,排查了半天才发现是参数组合问题。
5.2 命令不存在或提示参数错误
如果你的终端提示 error: unrecognized subcommand 'list',说明 Ruff 版本里还没有这个子命令。这时候有两个选择:升级 Ruff,或者用 ruff rule 来替代查询。
老版本的 ruff rule 不带参数也能列出规则,只是输出格式和命令名称不同。快速验证一下:
bash复制ruff rule --help
如果 rule 子命令存在,看一下它支持的参数,通常也能满足需求。不过我还是建议直接升级到新版,因为 list 子命令的输出更适合定位和筛选。
5.3 输出太多、不好阅读怎么办
N 规则的数量并不算特别多,但如果你用的是 --select ALL,输出量就会很大。这时候有两个处理技巧。
一是用 grep 过滤。假如你只想看含 argument 的 N 规则,可以在终端里加管道:
bash复制ruff list --select N | grep argument
二是直接输出 JSON,交给脚本或编辑器处理:
bash复制ruff list --select N --output-format json > n_rules.json
然后你可以用 Python、jq 或其他工具对 JSON 做结构化分析,整理成团队规则表。
5.4 配置了 N 规则却没生效怎么办
这是很多人踩过的问题:pyproject.toml 里写了 select = ["N"],但运行 ruff check 时,明明代码有命名问题,却没有任何提示。
首先检查配置是否写对了位置。Ruff 的 lint 配置必须放在 [tool.ruff.lint] 下面,不是 [tool.ruff] 下面。写错位置的话,Ruff 不会报错,但配置也不会生效。其次检查有没有被 ignore 覆盖,ignore 列表优先于 select,如果 ignore 里写了 N802,那就别指望 N802 再提示。最后,确认你检查的文件路径是在 Ruff 默认扫描范围内,或者你明确指定了文件:
bash复制ruff check src/
5.5 常见问题速查表
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
ruff list --select N 输出为空 |
版本过旧 / 前缀不存在 / 被过滤参数排除 | 升级 Ruff,确认前缀,简化参数 |
提示 unrecognized subcommand 'list' |
Ruff 版本较旧 | 升级 Ruff,或用 ruff rule --help |
| 输出文本太杂 | 输出格式不适合阅读 | 用 grep 或 --output-format json |
| 配置了 N 规则但不生效 | 配置位置错误 / 被 ignore 覆盖 | 检查 [tool.ruff.lint] 和 ignore 列表 |
| 不确定规则含义 | 文档没看明白 | 用 ruff rule N806 查看详情 |
最后再分享一个小技巧
我在实际项目里使用 ruff list --select N 时,最常用的一个组合是配合 JSON 输出,把它接到一个小脚本里,自动生成当前版本的 N 规则清单,然后丢到团队文档里。这样即使 Ruff 升级后规则变动,文档也能跟着更新,不会出现“代码规范文档和真实检查结果不一致”的尴尬。如果你也在维护团队的 Python 风格规范,可以试试这个思路,能省掉不少手工维护的力气。
