Python Linter 比较 2022:Pylint vs Pyflakes vs Flake8 vs autopep8 vs Bandit vs Prospector vs Pylama vs Pyroma vs Black vs Mypy vs Radon vs mccabe
从冗长的标题可以看出,Python 有很多 linting 工具。 他们中的一些人的名字几乎相同。 2022 年 11 月,我将我的文本编辑器升级到 Sublime Text 4,然后借此机会花了几个小时回顾了我能找到的所有 Python linter。 在亲自审查了所有这些之后,我选择了以下作为必备工具:Pyflakes、Mypy 和 Black。 如果您想要其他工具,我也喜欢:Radon、Pyroma 和 docformatter。 我正在使用 Python 3.12.0。 当我偏离 PEP 8 文档中的某些规定时,我不关心我的 linter 会指出什么,我的 linter 选择反映了这一点。 您可能有与我不同的需求和价值观,因此在这篇博文中,我对每个 linter 给出了我的推理和观点。
您可以使用 PyCharm Community Edition 和 Microsoft Visual Studio Code 等已经为您设置了集成 linter 的 IDE 来跳过大部分讨论。 但是如果您想自定义您的开发环境,这篇博文会很有帮助。
Linter 是一个过于宽泛的术语,指的是一种在不运行源代码的情况下检查源代码(也称为静态代码分析)以指出可能存在的问题的工具。 这个预警系统可以加快您的开发速度,因为您可以在开发过程的早期修复它们,而不是等待 QA 或用户指出它们。 棉绒这个词来自干衣机棉绒陷阱如何从衣服上去除小块绒毛。 我将这些工具分为以下几类:
- 类型检查器验证您的程序是否遵循它们自己的类型注释(也称为类型提示)。 (Mypy、Pyright、Pyre、Pytype)错误 linters 指出语法错误或其他将导致未处理的异常和崩溃的代码。 (Pylint, Pyflakes, Flake8) Style linters 指出不会导致错误但会降低代码可读性或不符合 Python 的 PEP 8 文档等风格指南的问题。 (Pylint、Flake8)Packaging linters 指出了与打包代码相关的问题,以便使用格式正确的描述、版本和元数据字段在 PyPI 上分发。 (Pyroma) 安全 linters 指出您的代码中可能存在的安全漏洞。 (Bandit) 代码格式化程序改变你的代码风格(主要围绕适当的空格)而不影响程序的行为。 (黑色)死代码 linters 从您的程序中删除注释掉的代码,因为应该跳过这种做法以支持适当的版本控制。 (Vulture, eradicate) Docstring linters/formatters 指出(并可能正确格式化)docstrings 中不符合 Python 的 PEP 257 文档的样式问题。 (pydocstringformatter, docformatter) 复杂性分析器指出代码太复杂以至于会影响可读性。 (麦凯布,氡)
许多这些 Python 包都包含其他 Python 包,如下表所述:
这个包……包括这些包 flake8Pyflakes, pycodestyle, mccabeautopep8pycodestylePylamapycodestyle, pydocstyle, Pyflakes, mccabe, Pylint, Radon, eradicate, Mypy, VultureProspectorPylint, flake8 (including Pyflakes, pycodestyle, mccabe), dodgy, isort, pydocstyle, pep8-命名
不合格包裹
PyChecker 立即停止运行,因为它自 2003 年以来就没有更新过,所以我跳过了对它的评估。 Pylava 也是如此,它是 Pylama 的一个分支,自 2020 年 9 月以来就没有更新过。我只想使用原始的 Pylama。
Mypy(类型检查器)
Mypy 不是 linter,而是静态类型检查工具。 无论您使用什么 Python linter,都应该安装和使用它。 Mypy 检查您放置在函数和变量上的类型提示(又名类型注释),并确保程序的其余部分正确遵循它们。 这是及早发现错误的好方法。 如果您需要了解更多信息,我写了一篇关于 Python 类型提示的博文。 Mypy 是第一个用于 Python 的静态类型检查器并且已经适合我的需要; 我还没有评估其他人:来自微软的 Pyright,来自 Facebook 的 Pyre(安装 pip install pyre-check
并不是 pip install pyre
), 和来自谷歌的 Pytype。
Pyflakes(错误短绒)
从 Pyflakes 项目页面:
Pyflakes 做出了一个简单的承诺:它永远不会抱怨风格,并且会非常非常努力地尝试从不发出误报。 Pyflakes 也比 Pylint 快。 这主要是因为 Pyflakes 仅单独检查每个文件的语法树。 因此,Pyflakes 在它可以检查的事物类型上更加有限。 如果你喜欢 Pyflakes 但也想要风格检查,你需要 flake8,它结合了 Pyflakes 和针对 PEP 8 的风格检查,并增加了每个项目的配置能力。
Pylint(错误和风格短绒)
从 Pylint 项目页面:
Pylint 是 Python 2 或 3 的静态代码分析器。Pylint 会在不实际运行代码的情况下分析您的代码。 它检查错误、执行编码标准、查找代码味道,并可以就如何重构代码提出建议。
Pylint 有大量文档。
您可以看到 Pylint 在此示例输出中指出的各种代码味道:
example.py:609:35: C0103: Argument name "n" doesn't conform to snake_case naming style (invalid-name) example.py:642:15: R1701: Consider merging these isinstance calls to isinstance(PAUSE, (float, int)) (consider-merging-isinstance) example.py:655:4: R1705: Unnecessary "elif" after "return", remove the leading "el" from "elif" (no-else-return) example.py:670:12: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return) example.py:675:12: W0707: Consider explicitly re-raising using 'except Exception as exc' and 'raise ImageNotFoundException from exc' (raise-missing-from) example.py:686:20: C0209: Formatting a regular string which could be a f-string (consider-using-f-string) example.py:771:17: W0212: Access to a protected member _position of a client class (protected-access) example.py:1038:0: R0913: Too many arguments (7/5) (too-many-arguments) example.py:1168:47: E1306: Not enough arguments for format string (too-few-format-args) example.py:1418:0: R0914: Too many local variables (17/15) (too-many-locals) ----------------------------------- Your code has been rated at 3.42/10
我更喜欢 Pyflakes 而不是 Pylint,尽管它正在运行 pylint --errors-only
删除样式建议并为我提供类似于 Pyflakes 的输出。 Pylint 往往比 Pyflakes 和 flake8 慢,并且会产生更多误报。 如果您想对代码特别彻底,我会使用 Pylint。
pycodestyle(样式短绒)
从 pycodestyle 项目页面:
pycodestyle 是一种根据 PEP 8 中的某些样式约定检查 Python 代码的工具。此包过去称为 pep8,但已重命名为 pycodestyle 以减少混淆。
pycodestyle 包含在 flake8、autopep8、Pylama 和 Prospector 中。
黑色(代码格式化程序)
Black 不是 linter,而是代码格式化程序,它可以在不改变程序行为的情况下更改源代码的间距和其他外观方面。 无论您使用什么 Python linter,都应该安装并使用它。 我更喜欢使用命令行参数运行它 black -l 120 -S yourScript.py
以便它格式化 yourScript.py 的行长度为 120(默认值为 88)并且不会更改字符串的引号(我喜欢使用单引号字符串,但 Black 将它们格式化为双引号字符串。)我在我的免费书籍的第 3 章,Beyond the Basic Stuff with Python
autopep8(风格短绒和格式化程序)
autopep8 使用 pycodestyle 来检测样式问题,然后自动更正它们。 与 pycodestyle 相比,我个人更喜欢 Black 格式化代码的方式。
pyupgrade(样式短绒)
我对 pyupgrade 持谨慎态度。 一方面,它似乎将 Python 语法更新为更现代的 Python 版本使用的语法。 另一方面,文档参差不齐,无法在做出更改之前看到它会做出哪些更改。 该项目似乎确实通过定期发布进行维护,但我想在向其他人推荐之前仔细评估它。
mccabe(复杂性分析)
mccabe 不是传统的 Python linter,而是测量圈复杂度。 圈复杂度(在 1976 年创建后也称为 McCabe 复杂度)测量通过某些源代码的线性独立路径的数量。 分数大于 10 的函数和方法通常被认为“太复杂”,应该简化。 在这种情况下,简化意味着使用更短的函数并删除重复代码。 对圈复杂度分数持保留态度; 如果有的话,只需使用分数作为您的源代码的哪些部分可能需要再次查看的指标。 不要将分数作为需要简化的硬性规则; 您最终会得到一个超载了比以前更难读的微小函数的程序。
mccabe 与 flake8、Pylama 和 Prospector 一起安装。
安装后,运行程序 python -m --min 10 mccabe example.py
. 最低分数为 10 的函数和方法的一些示例输出如下所示:
TryExcept 182 10 646:0: '_normalizeXYArgs' 13 826:0: '_normalizeButton' 10 1418:0: '_mouseMoveDrag' 11 1899:0: '_tokenizeCommandStr' 19 2025:0: '_runCommandList' 21
太棒了,我应该看看那个 _runCommandList
我写的功能,看看我是否可以简化它。
氡(复杂性分析)
Radon 包括用于执行圈复杂度测量的 mccabe 包,但也有用于测量 LOC(“代码行”)、Halstead 指标(基于运算符和操作数的数量来计算理解代码的“难度”)的选项,以及可维护性指数(使用 Microsoft Visual Studio IDE 使用的相同指标公式)。 文档中给出了如何计算这些指标。
例如,我对我的一些代码运行了这些 Radon 测量,输出如下所示:
C:UsersAlDesktoplintercmp>radon cc C:githubpyautoguipyautogui__init__.py githubpyautoguipyautogui__init__.py F 2025:0 _runCommandList - D F 1418:0 _mouseMoveDrag - C F 1899:0 _tokenizeCommandStr - C F 646:0 _normalizeXYArgs - C F 826:0 _normalizeButton - B F 1733:0 displayMousePosition - B --SNIP-- F 2157:0 getInfo - A C 28:0 PyAutoGUIException - A C 38:0 FailSafeException - A C 48:0 ImageNotFoundException - A C:UsersAlDesktoplintercmp>radon raw C:githubpyautoguipyautogui__init__.py githubpyautoguipyautogui__init__.py LOC: 2163 LLOC: 821 SLOC: 1048 Comments: 154 Single comments: 117 Multi: 593 Blank: 405 - Comment Stats (C % L): 7% (C % S): 15% (C + M % L): 35% C:UsersAlDesktoplintercmp>radon hal C:githubpyautoguipyautogui__init__.py githubpyautoguipyautogui__init__.py: h1: 19 h2: 329 N1: 268 N2: 524 vocabulary: 348 length: 792 calculated_length: 2831.7901243143224 volume: 6686.811248712193 difficulty: 15.130699088145896 effort: 101176.1288634933 time: 5620.89604797185 bugs: 2.2289370829040647 C:UsersAlDesktoplintercmp>radon mi C:githubpyautoguipyautogui__init__.py githubpyautoguipyautogui__init__.py - B
您需要仔细阅读文档以弄清楚确切的含义,因为它的可读性不是很好(足够有趣)。 我不会说 Radon 与类型检查器或错误 linter 一样必要,但它可以提供有关代码一般大小的有用信息。 确保不要将指标与实际质量混淆。
flake8(错误和样式 Linter,复杂性分析)
Flake8 是 Pyflakes、pycodestyle 和 mccabe 的捆绑包,并将这些程序的输出合并在一起。 它类似于 Pylint,但也包含 mccabe 包。 如果您想同时运行这几个工具,请使用它。
Pylama(“厨房水槽”)
Pylama 是 kitchen sink,包含几个 linters 和其他工具:pycodestyle(样式 linter)、pydocstyle(docstring linter)、Pyflakes(错误 linter)、mccabe(复杂性分析)、Pylint(错误和样式 linter)、Radon(复杂性分析) , eradicate(死代码 linter),Mypy(类型检查器),Vulture(死代码 linter)。
我不确定让所有这些工具在您的源代码上运行有多实用,并且肯定需要微调以限制误报。 但是,如果您查看了这篇博文并想在一个包中下载所有这些工具,Pylama 可以做到这一点。 Pylama 和 Prospector 是类似的“厨房水槽”包,但截至 2022 年 11 月,它们似乎需要不同版本的捆绑包,并且不能同时…