广告位 · 页头(后台-模块管理-新建模块后替换此区域)

pyright 如何设置才能严格检查未使用的 import

在日常维护 Python 项目时,编辑器里偶尔飘过的灰色波浪线提示某个 import 从未被使用,很多人可能并不会立刻处理。如果团队没有统一的静态检查策略,这些未使用的 import 会慢慢堆积,轻则让代码显得凌乱,重则在重构时造成误导。pyright 默认能够检测未使用的 import,但它默认的严重级别只是 warning 或者 information,不会直接中断检查流程。要让 pyright 在这方面严格起来,需要手动调整配置。

pyright 如何设置才能严格检查未使用的 import

pyright 的配置入口主要有两个:独立的 pyrightconfig.json 文件和 pyproject.toml 中的 [tool.pyright] 段落。两者功能基本一致,只是存放位置和语法稍有区别。其中与未使用 import 直接相关的参数是 reportUnusedImport。这个参数控制的是“导入但未使用”的诊断级别,可选项包括 none、information、warning、error。默认值是 warning,也就是说默认情况下 pyright 会提示但不会把 CI 跑挂。要实现严格检查,需要把它设为 error。

基础配置:reportUnusedImport 设为 error

先从最简单的场景说起。假设项目根目录下有一个 pyrightconfig.json,内容可以写成下面这样:

{
  "include": ["src"],
  "reportUnusedImport": "error"
}

这份配置告诉 pyright 只检查 src 目录下的 Python 文件,并且把任何未使用的 import 都当作错误。运行 pyright 命令时,如果代码中存在 import os 但后续没有使用 os 这个名称,pyright 会输出一条错误信息,并且以非零状态码退出。这在本地开发和 CI 中都能起到强制作用。

如果项目使用 pyproject.toml 管理配置,可以这样写:

[tool.pyright]
include = ["src"]
reportUnusedImport = "error"

需要注意,pyright 的配置项名称区分大小写,reportUnusedImport 必须完全一致。另外,pyright 只会对包含在 include 或 exclude 范围内的文件进行诊断,如果文件不在 include 列表中,即使配置了 reportUnusedImport 也不会生效。因此确保 include 路径覆盖了所有需要检查的源码目录。

进阶用法:针对单文件或目录的豁免与覆盖

整个项目把所有未使用 import 都设为 error 虽然严格,但有时会遇到一些边缘情况,比如在 __init__.py 中为了重新导出符号而故意 import,或者某些动态导入的场景。这时可以通过 pyright 的 override 机制对特定文件或目录设置不同的严重级别。

在 pyrightconfig.json 中可以使用 executionEnvironments 或者 override 字段。推荐使用 override,它支持按 glob 模式匹配文件路径,并覆盖任意诊断设置。例如:

{
  "include": ["src"],
  "reportUnusedImport": "error",
  "override": [
    {
      "files": ["src/legacy/**"],
      "reportUnusedImport": "warning"
    },
    {
      "files": ["src/package/__init__.py"],
      "reportUnusedImport": "none"
    }
  ]
}

上面的配置表示:默认所有文件未使用 import 都是 error;src/legacy 目录下的所有文件降为 warning,只做提示不阻塞;src/package/__init__.py 完全关闭这项诊断,因为重新导出符号是合理行为。override 数组的匹配顺序很关键,后面的规则比前面的优先级更高,如果文件同时匹配多条规则,以最后一条为准。

在 pyproject.toml 中的写法类似,使用 [[tool.pyright.override]] 表格数组:

[tool.pyright]
include = ["src"]
reportUnusedImport = "error"
[[tool.pyright.override]]
files = ["src/legacy/**"]
reportUnusedImport = "warning"
[[tool.pyright.override]]
files = ["src/package/__init__.py"]
reportUnusedImport = "none"

需要注意的是,glob 模式中的 ** 表示递归匹配任意层级目录,* 只匹配单层。如果要精确匹配某个文件,直接写相对路径即可。这种细粒度控制可以避免“一刀切”带来的误报,让严格检查更具可操作性。

与编辑器和其他工具的配合

pyright 本身可以作为命令行工具运行,也可以作为语言服务器嵌入 VS Code、Neovim 等编辑器。在 VS Code 中安装 Pylance 或 pyright 扩展后,编辑器的诊断直接反映配置结果。当 reportUnusedImport 设为 error 时,未使用的 import 会以红色波浪线显示,并且能通过“快速修复”自动删除。

如果想在更大的工程化流程中串联使用,可以结合 pre-commit 或 CI 步骤。例如在 GitHub Actions 中运行 pyright --level error,或者直接用 pyright 并依赖配置中的 error 级别。值得注意的是,pyright 的 --level 参数可以临时提高所有诊断的最低级别,如果传入 --level error,即使配置中某些项是 warning,也会被提升为 error。但相反,如果配置中已经是 error,则不会因为命令行参数而降低。所以稳妥的做法是配置文件里写清楚,命令行只做常规调用。

此外,pyright 还提供了 reportUnusedVariable、reportUnusedClass、reportUnusedFunction 等相近参数,分别控制局部变量、类、函数的未使用检测。如果你希望把未使用的局部变量也设为 error,可以一并调整。不过这类检查有时会对解构赋值中的下划线变量产生误报,pyright 对以单下划线开头的名称默认不做未使用提示,这一点在多数情况下不需要额外处理。

总体来看,让 pyright 严格检查未使用的 import 只需要改一个配置项,但把它融入团队工作流还需要考虑豁免规则和工具链整合。通过 error 级别强制、override 精确控制、以及编辑器联动,可以高效保持 import 列表的整洁,减少技术债务。

广告位 · 文章底部(后台-模块管理替换此区域)