大规模编写和 lint Python
Meta 在 Fixit 2 上的工作——一个基于 libcst、可自动修复的 Python linter——引发了更广泛的讨论:如何借助更强的工具、类型注解和自动化代码转换,让 Python 在大规模场景下可用。评论者将 Python 日益壮大的静态类型生态和各类 linter(包括 Ruff 和 Fixit)与 TypeScript、C# 等语言进行对比,争论动态语言究竟适不适合作为大型系统的基础,还是只是靠“创可贴式”工具勉强维持。另一些人则更关注实际取舍:Python 的调试便利和快速开发能力,与其性能限制、线程问题,以及真实代码库中类型注解和库质量参差不齐之间的权衡。
讨论的背景与工具
- 线程围绕 Meta 的 Fixit 2 Python linter 展开,它建立在 libcst 之上,同时也讨论了在大规模场景下对 Python 进行 lint 和类型检查的更广泛经验。
- Fixit 2 的一个显著特性是:lint 规则不仅能报告问题,还能自动应用代码更改。
对自动修复型 linter 的信任与工作流
- 有些人对会自动更改代码、且超出格式化/导入范围的 linter 持谨慎态度。
- 也有人指出,C#/.NET、ESLint 和 Rubocop 等生态里,自动修复是标准且高效的,尤其是在以下情况下:
- 修复是在提交后或通过代码评审、并经明确接受后应用。
- 只自动应用“安全”类别的修复。
- 建议的工作流是:先提交,再运行自动修复,然后检查 diff。
Ruff vs Flake8 及其他 linter
- Ruff 的优点包括:
- 极快的速度。
- 将格式化、lint 和导入排序整合到一个工具中。
- 能发现一些 flake8 插件遗漏的问题。
- 批评包括:
- 在大型、混乱的遗留代码库上,与原始 flake8 插件的行为不一致。
- 过去某些自动修复会引入新问题;新版本的 Ruff 已区分“安全”和“不安全”的修复。
- 线程中的 Ruff 维护者表示:
- 他们的目标是达到与插件相同或更好的正确性,并欢迎 bug 报告。
- lint/fix 是迭代进行的,直到不再有可修复的问题为止。
- 几位评论者表示,他们已在许多项目中成功采用 Ruff,且几乎没有问题。
大规模 Python:动态类型 vs 静态类型
- 对 Python(以及类似“动态脚本语言”)是否适合大型系统,存在强烈分歧:
- 批评者认为:大公司最终会重建静态类型和繁重工具;如今静态语言原型开发已经足够快,因此从动态语言开始是个错误。
- 支持者认为:Python 的可选类型系统、和类型、模式匹配以及外部检查器,使其仍然可行,并且越来越“安全”。
- 还有很长的子线程在争论术语(“动态语言”“动态类型”)和类型理论细节:递归类型(JSON)、可变参数泛型、元组拼接,以及与 TypeScript 和 Haskell 的比较。
Python 的优点与缺点
- 支持者强调:
- 调试容易,运行时错误清晰。
- 语法好,适合教学。
- 类型注解正在提高大型代码库的可扩展性。
- 批评者则认为:
- 就工程价值而言,Python 从来不是“最佳”工具;流行度和临时补丁式工具占了主导。
- 性能和线程(GIL)仍然是真实的扩展限制;规避办法往往涉及子进程。
对统一工具链的需求
- 有些人希望有一个单一工具来处理格式化、lint、排序和 pre-commit 检查,更看重一致性而不是具体风格。
- Ruff 被视为一个有希望的候选者;其资金支持被认为可能加速朝着“单工具”一致性的方向发展,甚至可能取代当前碎片化的 pre-commit 生态。