Ruff 如何配置 src 与 known-third-party 来判定导入是 first-party 还是 third-party
2026/9/11 7:10:02 网站建设 项目流程

Ruff 如何配置 src 与 known-third-party 来判定导入是 first-party 还是 third-party

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

在 Ruff 里启用 isort 导入排序(I001)后,Ruff 必须先把每个导入归类为 standard-library、first-party 或 third-party,才能把它们排进正确的分组。归类错误的直接后果是:本地模块和依赖包的导入被排到错误的区块,I001报出的排序结果不符合预期。这篇文章讲清楚 Ruff 是怎么做这个判定的,以及当判定结果不对时,如何用srcknown-third-party两个配置项修正。

Ruff 判定 first-party 的规则

Ruff 接受一个顶层src选项,写在pyproject.tomlruff.toml.ruff.toml中,指定它在判断导入是否为 first-party 时要查看的目录。

假设项目结构如下:

my_project ├── pyproject.toml └── src └── foo ├── __init__.py └── bar ├── __init__.py └── baz.py

当 Ruff 看到import foo时,它会遍历所有src目录,寻找对应的 Python 模块——实际上就是名为foo的目录或名为foo.py的文件。规则因导入形式而异:

  • import foo:在src目录下找foo目录或foo.py文件;
  • import foo.bar这类多组件路径:要求foo/bar完整相对路径以目录形式存在,或者foo/bar.pyfoo/bar.pyi以文件形式存在;
  • from foo import bar:只用foo这个顶层模块名来判断它属于 first-party 还是 third-party。

如果src字段被省略,Ruff 默认使用"项目根目录"加上src子目录作为 first-party 来源,以同时兼容扁平布局和嵌套布局。项目根目录通常是包含pyproject.tomlruff.toml.ruff.toml的目录;除非通过--config选项在命令行提供了配置文件,此时用当前工作目录作为项目根。

除此之外还有一个同包启发式:Ruff 会尝试确定某个 Python 文件当前所属的包(通过目录中是否存在__init__.py判断),并把该文件内来自同一个包的导入标记为 first-party。比如在上面结构中,baz.py属于从./my_project/src/foo开始的包,因此baz.py里以foo开头的导入(如import foo.bar)会被判为 first-party。

用 src 明确 first-party 来源

默认行为把"项目根 +src子目录"都算作 first-party 来源。如果你想让src成为唯一明确的 first-party 来源,可以显式设置(路径相对于项目根,即包含pyproject.toml的目录):

[tool.ruff] # Ruff 支持顶层 src 选项,作为 isort src_paths 设置的替代。 # 所有路径都相对于项目根,即包含 pyproject.toml 的目录。 src = ["src"]

等价的ruff.toml写法(省略[tool.ruff]头):

# Ruff 支持顶层 src 选项,作为 isort src_paths 设置的替代。 # 所有路径都相对于项目根,即包含 pyproject.toml 的目录。 src = ["src"]

如果你的pyproject.tomlruff.toml.ruff.toml通过extend继承了另一个配置文件,注意项目根仍是你自己的配置文件所在目录,而不是被继承文件所在的目录。例如在tests目录下加一个配置文件时,需要在继承的配置中显式写回src

[tool.ruff] extend = "../pyproject.toml" src = ["../src"]

用 known-third-party 纠正误判

上面基于src的算法有一个已知边界:如果某个目录名与某个第三方包同名,但该目录里并没有 Python 代码,Ruff 可能把对应的导入错误地推断为 first-party。典型场景是你import wandb,同时src下又有一个叫wandb的子目录。这时用known-third-party显式声明模块归属:

[tool.ruff.lint.isort] known-third-party = ["wandb"]

ruff.toml中的等价写法:

[lint.isort] known-third-party = ["wandb"]

反向场景也支持:如果某个模块无论位于文件系统何处都应被视为 first-party,可以设置known-first-party

[tool.ruff] src = ["src", "tests"] [tool.ruff.lint] select = [ # Pyflakes "F", # Pycodestyle "E", "W", # isort "I001" ] [tool.ruff.lint.isort] known-first-party = ["my_module1", "my_module2"]

注意select中必须包含I001,否则导入排序规则本身不会生效,分类结果也无从体现。

验证判定结果

改完配置后有两步可以核对:

  1. 跑一次检查,确认I001报出的导入排序与预期分组一致:
$ ruff check .
  1. --show-settings查看 Ruff 针对某个文件实际解析出的配置,确认srcknown-third-party等值确实生效:
$ ruff check /path/to/code.py --show-settings

限制

  • Ruff 尚未支持 isort 的全部配置选项,已支持的 isort 设置清单见 settings 文档的 lint.isort 部分(FAQ 原文指向 API reference 的lint.isort章节)。
  • 判定只依据文件系统结构:目录存在与否、是否含 Python 代码,都会影响推断结果,遇到与第三方包同名的本地目录时必须用known-third-party显式纠正。
  • from foo import bar只看顶层模块foobar本身不参与 first-party/third-party 的判定。

更详细的src解析机制说明在 FAQ 中指向了 contributing 指南,配置语义以当前版本的ruff check --show-settings输出为准。

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询