内容提要
Ruff v0.0.281 发布,词法分析器提速 2-3 倍,优化数据结构和分配,有利于 linter 和未来格式化器。文件级 # ruff: noqa 行尾注释现被忽略并警告。新增规则:PYI018、PYI046、PYI047、PYI049 检查未使用的私有类型定义,PYI056 禁止对 __all__ 调用 append 等方法,PLW0127 检查自我赋值,PLW1509 警告 preexec_fn,PTH206、PTH207 建议用 pathlib 替代 os.sep.split 和 glob。
延伸解读
词法分析器提速对工具链的影响
Ruff 的词法分析器在 v0.0.281 中实现了 2-3 倍的性能提升,这得益于更缓存友好的数据结构、更少的内存分配以及对纯 ASCII 源码的优化。由于词法分析是每个文件分析的第一步,这一改进不仅直接加速了 linter 本身,也为未来基于同一词法分析器的工具(如格式化器)奠定了性能基础。
文件级 noqa 注释的行为变更
此前,Ruff 会尊重出现在行尾的文件级 # ruff: noqa 抑制注释,但这很可能是一个错误用法。新版本中,这类行尾注释将被忽略并发出警告。如果只想抑制单行的错误,应使用 # noqa: F401 这样的行内注释,而不是文件级注释。这一变更有助于避免因误用而意外禁用整个文件的检查。
新增规则聚焦类型注解与代码质量
本次更新引入了多条来自 flake8-pyi 和 Pylint 的规则。PYI018、PYI046、PYI047、PYI049 分别检查未使用的私有 TypeVar、Protocol、TypeAlias 和 TypedDict 定义,提示开发者应使用、公开或删除它们。PYI056 禁止对 __all__ 调用 append 等方法,建议改用 += 运算符以确保类型检查器兼容。PLW0127 检查自我赋值,PLW1509 警告 preexec_fn 的线程不安全性和弃用趋势。
pathlib 替代建议的细节与差异
PTH206 和 PTH207 规则鼓励使用 pathlib 替代 os.sep.split 和 glob。但需注意,glob.glob 与 Path.glob 并非完全等价:glob 默认排除隐藏文件,而 Path.glob 默认包含;glob 需要 recursive=True 才能启用 ** 递归匹配,而 Path.glob 中的 ** 直接表示递归。此外,Path.glob 返回迭代器,而 glob.glob 返回列表。迁移时需留意这些行为差异。
Q&A
Ruff v0.0.281 中词法分析器的性能提升了多少?
Ruff v0.0.281 的词法分析器比之前版本快了 2-3 倍。
Ruff 对文件级 # ruff: noqa 行尾注释的处理有什么变化?
Ruff 现在会忽略并警告文件级的行尾 # ruff: noqa 注释,因为它们很可能是错误。
Ruff 新增了哪些检查未使用私有类型定义的规则?
新增了 PYI018(未使用的私有 TypeVar)、PYI046(未使用的私有 Protocol)、PYI047(未使用的私有 TypeAlias)和 PYI049(未使用的私有 TypedDict)。
为什么应该避免对 __all__ 调用 append 等方法?
因为不同类型检查器对这些方法的支持程度不同,建议使用 += 运算符来添加元素。
Ruff 新增的 PLW1509 规则是关于什么的?
该规则警告使用 subprocess.Popen 的 preexec_fn 参数,因为它在线程中不安全且可能被弃用,建议改用 start_new_session 或 process_group 等参数。
Ruff 建议用什么替代 os.sep.split 和 glob?
建议使用 pathlib 模块中的 Path 对象方法,如 Path.name、Path.parent、Path.parts 和 Path.glob()。