Python代码扫描:新一代 Python Linter工具Ruff -极力推荐-快的原因是Rust写的?

目录

RUFF概述

特点

安装和使用

应用场景

配置

编辑器集成

PyCharm(外部工具)

Ruff的规则

Ruff速度快的几个原因

最后


注意:后续技术分享,第一时间更新,以及更多更及时的技术资讯和学习技术资料将在公众号CTO Plus发布,请关注公众号:CTO Plus

Ruff是一个基于Python的代码检查工具,它可以帮助我们在编写Python代码时发现潜在的问题并提供修复建议。本文我将在Python3.11版本下,介绍Ruff的特点、使用方法以及在项目中的应用场景。

最近几年Rust在前端工具链领域影响越来越大,甚至提出了《Rust 是 JavaScript 基建的未来》,凡是能用 Rust 重写的前端工具就用 Rust 重写,结果突出一个字 - 快。这股风气也被悄然带入到了其他解释性语言领域,Ruby 使用 Rust 实现 YJIT 编译器;在 Python 语言领域,出现了 Ruff 项目,官方简介:

一个用Rust编写的非常快速的Python linter:比现有的 linter 快 10-100 倍⚡️

在公众号CTO Plus的这篇文章对Rust做了一个基本介绍《Rust:一门安全、并发和高性能的系统编程语言,能为我们带来哪些利好》,具体可以参考这篇文章,后面我将对Ruff的源码进行深度剖析,这里先简单看下他的源码结构。

从源码中可以看出,项目工程用的是Rust的Cargo构建工具,这个工具将在文章《Rust进阶1. 安装Rust编程环境,并编写你的第一个Rust程序,以及两款rustc、cargo工具使用方法和常用指令总结》中做介绍。

https://mmbiz.qpic.cn/sz_mmbiz_png/9TA6bnE8vklgnIicAz4aXMYwjPBBNFzic7ERLTef2GvDf0HEgJEWvJiafgQz4h2y3g1w1SOmexT8Slsl2URgBgvjg/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

在他的核心代码目录crates下,可以看到全是基于Cargo构建的标准Rust项目

https://mmbiz.qpic.cn/sz_mmbiz_png/9TA6bnE8vklgnIicAz4aXMYwjPBBNFzic7IMBWxR9a9YCy9kG8H8CQrfh0WbEiaMfTiaGoKia1Ew3KstXWus79FXDLQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

以及非常多的.rs文件,.rs文件是Rust编写的源码问题,同比.py是Python的源码文件。

https://mmbiz.qpic.cn/sz_mmbiz_png/9TA6bnE8vklgnIicAz4aXMYwjPBBNFzic7Zg2NlaVNaO8icuM7r0I2a7TIZKBtibVfpsfVoSZCibqbKC7gpia13Att8A/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

本篇属于【代码规范与扫描】系列内容的第三篇,前面几篇可以根据自己情况执行查阅:

  1. 企业级Python代码静态扫描-代码规范、逻辑、语法、安全检查,以及代码自动编排介绍
  2. 通读Python PEP8代码规范
  3. Python代码扫描:新一代 Python Linter工具Ruff
  4. Python代码扫描:提升Python代码质量的神器-pylint详解与使用指南
  5. Python代码扫描:轻量级Python静态代码分析工具pyflakes
  6. Python代码扫描:Python代码规范与错误检查的利器-flake8详解与实践
  7. Python代码扫描:静态类型检查的最佳选择mypy
  8. Python代码扫描:自动化移除Python代码中的冗余-autoflake使用技巧与实例
  9. Python代码扫描:Python代码格式化的利器-yapf详解与最佳实践
  10. Python代码扫描:一键格式化Python代码的黑魔法-black使用教程
  11. Python代码扫描:导入语句自动排序工具-isort使用指南与示例
  12. Python代码扫描:自动化修复Python代码风格的工具-autopep8详解与实例
  13. Python代码扫描:项目中的代码规范与错误检查-pyproject-flake8配置与使用方法
  14. Python代码扫描:企业级代码代码安全漏洞扫描Bandit

RUFF概述

Ruff第一个版本发布在2022年8月30日,可以说是一个非常新的项目,虽然作者迭代的非常积极(目前版本为 v0.0.198),但是规则实现上没有常用的 Pylint 规则多,并不能完全替代 Pylint。当前 Pylint 总共实现了409条规则,而Ruff实现了224条,其中有60条与 Pylint 规则集重叠。主观上,Pylint倾向于实现更多基于类型推断的规则(例如,验证函数调用中参数的数量)。关于 Pylint 规则替代实现官方也有跟踪,详见 #970。Ruff 目前还不支持第三方插件,仅仅在项目范围内有一个插件系统,详见 https://github.com/astral-sh/ruff/issues/283。

Ruff 利用 Rust Python 的 AST 解析器,实现自己的 AST 遍历、visitor 抽象和 lint 规则逻辑。它目标是比其他工具快几个数量级,同时提供代码检查、autofix等一站式的解决方案。

Ruff 可以用来替换flake8(加上各种插件)、isortpydocstyleyesqaeradicatepyupgrade和 autoflake,所有这些都比任何单独的工具执行速度快几十或数百倍。Ruff 超越了传统 linter 的职责,而是作为一种高级代码转换工具,能够升级类型注释、重写类定义、对import导入进行排序等等。

特点

Ruff具有以下几个特点:

1. 首先是速度快、功能强大。

2. 定制规则:Ruff提供了一系列的默认规则,同时也支持自定义规则。我们可以根据项目的需求定义自己的规则,以满足特定的代码质量要求。

3. 代码风格检查:Ruff可以检查代码的风格是否符合PEP 8规范,如缩进、命名规范、代码布局等。

4. 代码质量检查:Ruff可以检查代码中的一些常见问题,如未使用的变量、未使用的导入、重复的代码等,以提高代码的量和可维护性。

5. 静态分析:Ruff通过静态分析Python代码来检查潜在的问题,不需要运行代码即可发现潜在的错误和不规范的代码。

6. 报告生成:Ruff可以生成详细的报告,包括每个问题的描述、位置和建议的修复方法。这些报告可以帮助我们快速定位和解决代码中的问题。

下面简单介绍下用法:

安装和使用

安装上非常简单,借助于maturin,Ruff 可以像其他第三方Python包一样通过pip安装,只需按照以下步骤进行操作:

1. 安装Ruff:可以通过pip命令安装Ruff,如下所示:

pip install ruff

安装完成后,在D:\env311\Scripts目录下即可看到一个ruff.exe的可执行文件

2. 执行检查:在命令行中执行以下命令,即可对指定的Python代码进行检查:

扫描指定目录:ruff /path/to/code

这将对指定路径下的所有Python文件进行检查,并生成相应的报告。

针对指定文件扫描

ruff path/to/code/to/check.py

使用通配符进行扫描

ruff path/to/code/*.py

还可以在watch模式下运行 Ruff,当文件改变时自动执行:

ruff path/to/code/ --watch

按照不同的目录和文件执行检查

ruff check .                        # Lint all files in the current directory (and any subdirectories)

ruff check path/to/code/            # Lint all files in `/path/to/code` (and any subdirectories)

ruff check path/to/code/*.py        # Lint all `.py` files in `/path/to/code`

ruff check path/to/code/to/file.py  # Lint `file.py`

也可以和 pre-commit 一起工作:

- repo: https://github.com/charliermarsh/ruff-pre-commit

  # Ruff version.

  rev: 'v0.0.198'

  hooks:

    - id: ruff

      # Respect `exclude` and `extend-exclude` settings.

      args: ["--force-exclude"]

3. 解读报告:Ruff将生成一个报告文件,其中包含了检查结果和问题的详细信息。我们可以根据报告中的建议来修复代码中的问题。

应用场景

Ruff可以在许多项目中应用,特别是在大型项目和团队协作中。以下是Ruff的一些应用场景:

1. 代码规范:对于遵循PEP 8规范的项目,Ruff可以帮助我们检查代码的风格是否符合规范,并提供相应的修复建议。

2. 代码质量:Ruff可以帮助我们检查代码中的一些常见问题,如未使用的变量、未使用的导入和重复的代码等,以提高代码的质量和可维护性。

3. 团队协作:在团队协作中,Ruff可以帮助我们统一代码风格和质量标准,以提高代码的一致性和可读性。

4. 持续集成:在持续集成环境中,Ruff可以作为一个检查步骤,帮助我们在代码提交前发现问题,以避免将错误的代码合并到主分支。

配置

Ruff 可以通过pyproject.toml和命令行进行配置。有关可配置选项的完整列表,请参阅 API文档。 默认配置如下:

[tool.ruff]
line-length = 88

# Enable Pyflakes `E` and `F` codes by default.
select = ["E", "F"]
ignore = []

# Exclude a variety of commonly ignored directories.
exclude = [
    ".bzr",
    ".direnv",
    ".eggs",
    ".git",
    ".hg",
    ".mypy_cache",
    ".nox",
    ".pants.d",
    ".ruff_cache",
    ".svn",
    ".tox",
    ".venv",
    "__pypackages__",
    "_build",
    "buck-out",
    "build",
    "dist",
    "node_modules",
    "venv",
]
per-file-ignores = {}

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

# Assume Python 3.10.
target-version = "py310"

[tool.ruff.mccabe]
# Unlike Flake8, default to a complexity level of 10.
max-complexity = 10

当然也可以自定义配置。例如,下面将配置Ruff 为:

避免检查line-length问题(E501)

不移除未使用的import(F401)

忽略在文件__init__.py中的import-at-top-of-file错误(E402)

[tool.ruff]
# Enable Pyflakes and pycodestyle rules.
select = ["E", "F"]

# Never enforce `E501` (line length violations).
ignore = ["E501"]

# Never try to fix `F401` (unused imports).
unfixable = ["F401"]

# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
[tool.ruff.per-file-ignores]
"__init__.py" = ["E402"]
"path/to/file.py" = ["E402"]

Ruff 模仿了 Flake8 的错误代码系统,其中每个错误代码由一个1-3个字母的前缀组成,后面跟着3个数字(例如F401)。前缀表示错误代码的“源”(例如,F表示Pyflakes, E表示pycodestyle, ANN表示flake8-annotations)。启用的错误集由select和ignore选项决定,它们既支持完整的错误代码(例如F401),也支持前缀(例如F)。

Ruff 也支持自己的配置文件ruff.toml(类似于 ESLint 的 .eslintrc),层级上少了 [tool.ruff],例如:

# Enable Pyflakes and pycodestyle rules.
select = ["E", "F"]

# Never enforce `E501` (line length violations).
ignore = ["E501"]

# Always autofix, but never try to fix `F401` (unused imports).
fix = true
unfixable = ["F401"]

# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
[per-file-ignores]
"__init__.py" = ["E402"]
"path/to/file.py" = ["E402"]

也可以通过命令行提供一些常见的配置设置:

ruff path/to/code/ --select F401 --select F403

类似于 ESLint, Ruff 支持分层配置,Python文件以距离它“最近的”的pyproject.toml作为其配置。和 ESLint 不同的是 Ruff 不会跨配置文件合并设置;相反,使用“最近的”配置文件,并且忽略任何父配置文件。代替这种隐式级联,Ruff 支持一个扩展字段,它允许我们从另一个pyproject.toml继承设置。像这样:

# Extend the `pyproject.toml` file in the parent directory.

extend = "../pyproject.toml"

# But use a different line length.

line-length = 100

上述规则同样适用于ruff.toml配置文件。 在代码中可以使用 # noqa: {code}注释忽略代码行/块的错误:

# Ignore F841.

x = 1  # noqa: F841

# Ignore E741 and F841.

i = 1  # noqa: E741, F841

# Ignore _all_ errors.

x = 1  # noqa

当前支持的规则参见:https://github.com/charliermarsh/ruff#supported-rules

编辑器集成

PyCharm(外部工具)

Ruff 可以在 PyCharm 中作为外部工具安装。打开首选项,然后导航到工具>外部工具。在那里,添加一个具有以下配置的新工具:

Ruff可以作为一个可运行的action。

Ruff的规则

Ruff支持500多个lint规则,其中许多规则的灵感来自流行的工具,如Flake8、isort、pyupgrade等。无论规则的起源如何,Ruff都将Rust中的每一条规则作为第一方功能重新实现。具体官方参考规则库:https://beta.ruff.rs/docs/rules/

默认情况下,Ruff启用Flake8的E和F规则。Ruff支持F类的所有规则,以及E类的一个子集,省略了那些因使用自动格式化程序(如Black)而过时的风格规则。
关于Flake8和Black将在公众号CTO Plus后面的文章中做详细介绍,敬请关注。

如果你刚开始使用Ruff,那么默认规则集是一个很好的起点:它可以在零配置的情况下捕获各种常见错误(如未使用的导入)。

除了默认设置之外,Ruff还重新实现了一些最流行的Flake8插件和相关的代码质量工具,包括:

  • autoflake
  • eradicate
  • flake8-2020
  • flake8-annotations
  • flake8-async
  • flake8-bandit (#1646)
  • flake8-blind-except
  • flake8-boolean-trap
  • flake8-bugbear
  • flake8-builtins
  • flake8-commas
  • flake8-comprehensions
  • flake8-copyright
  • flake8-datetimez
  • flake8-debugger
  • flake8-django
  • flake8-docstrings
  • flake8-eradicate
  • flake8-errmsg
  • flake8-executable
  • flake8-future-annotations
  • flake8-gettext
  • flake8-implicit-str-concat
  • flake8-import-conventions
  • flake8-logging-format
  • flake8-no-pep420
  • flake8-pie
  • flake8-print
  • flake8-pyi
  • flake8-pytest-style
  • flake8-quotes
  • flake8-raise
  • flake8-return
  • flake8-self
  • flake8-simplify
  • flake8-slots
  • flake8-super
  • flake8-tidy-imports
  • flake8-todos
  • flake8-type-checking
  • flake8-use-pathlib
  • flynt (#2102)
  • isort
  • mccabe
  • pandas-vet
  • pep8-naming
  • pydocstyle
  • pygrep-hooks
  • pylint-airflow
  • pyupgrade
  • tryceratops
  • yesqa

Ruff速度快的几个原因

Ruff它之所以能够运行得非常快速,可以归因于以下几个方面:

1. 采用 AST(抽象语法树)分析:Ruff 使用 Python 的内置库 ast 来解析源代码并生成抽象语法树。相比于直接解析源代码,AST 分析可以更高效地遍历和分析代码结构,从而提高性能。

2. 基于规则的静态分析:Ruff 通过定义一系列的规则来检查代码,这些规则可以检测出代码中的潜在问题和风格违规。相比于动态分析或符号执行等复杂的分析技术,基于规则的静态分析方法更加简单和高效。

3. 并行处理:Ruff 可以并行处理多个文件,从而提高分析的速度。它可以同时启动多个分析任务,每个任务独立运行,互不干扰。这样可以充分利用多核处理器的计算能力,加快分析的速度。

4. 优化算法:Ruff 使用了一些优化算法来提高分析的效率。例如,可以通过缓存已经分析过的模块,避免重复解析和分析;还可以通过剪枝等技术,减少不必要的分析路径,提高分析的效率。

最后

Ruff 还可以和Python另一个格式化工具black 一起使用,只需要 line-length有相同配置既可。关于black工具的详细介绍将在后面的文章《Python代码扫描:一键格式化Python代码的黑魔法-black使用教程》中做详细介绍,敬请关注公众号CTO Plus后面的文章。

Ruff是一个强大的Python代码检查工具,可以帮助我们发现潜在的问题并提供修复建议。它通过静态分析Python代码来检查代码风格和质量,并生成详细的报告。在代码规范、代码质量、团队协作和持续集成等场景中,Ruff都可以发挥重要的作用,帮助我们提高代码的质量和可维护性。

参考资料

GitHub - astral-sh/ruff: An extremely fast Python linter, written in Rust.

https://github.com/charliermarsh/ruff#supported-rules

Meta issue: plugin system · Issue #283 · astral-sh/ruff · GitHub

https://beta.ruff.rs/docs/tutorial/

https://beta.ruff.rs/docs/rules/

https://beta.ruff.rs/docs/configuration/

https://beta.ruff.rs/docs/settings/

Python代码规范:企业级代码静态扫描-代码规范、逻辑、语法、安全检查,以及代码规范自动编排(1)_pycharm 检查代码规范_SteveRocket的博客-CSDN博客

https://blog.csdn.net/zhouruifu2015/article/details/129877179

Python专栏
https://blog.csdn.net/zhouruifu2015/category_5742543


更多资料 · 微信公众号搜索【CTO Plus】关注后,获取更多,我们一起学习交流。

关于公众号的描述访问如下链接


更多精彩,关注我公号,一起学习、成长

关于Articulate“做一个知识和技术的搬运工。做一个终身学习的爱好者。做一个有深度和广度的技术圈。”一直以来都想把专业领域的技icon-default.png?t=N7T8https://mp.weixin.qq.com/s?__biz=MzIyMzQ5MTY4OQ==&mid=2247484278&idx=1&sn=2b774f789b4c7a2ccf10e465a1b9def6&chksm=e81c2070df6ba966026fd7851efa824b5e2704e3fd34e76228ca4ce64d93f7964cd4abe60f2b#rd

标准库系列-推荐阅读:


推荐阅读:

猜你喜欢

转载自blog.csdn.net/zhouruifu2015/article/details/131264480