找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2381

积分

0

好友

319

主题
发表于 16 小时前 | 查看: 7| 回复: 0

跑一下 ruff check,满屏的红线就出来了。不是说代码跑不起来,而是你突然发现自己这些年在 Python 里积攒的那些小毛病,被它一个个揪了出来,场面相当壮观。更让人头疼的是,这些问题平时用 flake8isortblack 分着跑,感觉不痛不痒。到了 Ruff 这里,它一把梭哈,速度快得像没干活儿,但该挑出来的问题一个都没少。

最开始我也不太信。Python 圈子里“一个工具替代一堆工具”的说法,通常都带着点营销的味道。但真正上手之后才发现,Ruff 不是来讲概念的,它是实实在在地来帮你缩短 CI 时间,顺手收拾掉代码里的坏味道的。

日常项目里最烦人的,往往不是没有规范,而是规范太分散、工具链太长。
一会儿要用 black 格式化代码,一会儿要用 isort 整理 import 顺序,一会儿还得跑 flake8 检查代码风格。要是再补点 pyupgradepylint 的规则,本地开发环境和 CI 跑出来的结果还可能不一致,平添不少沟通成本。

Ruff 的做法就很直接:它把上面这些常见的活儿都揽到自己身上,而且速度还快得离谱。你只要跑一次就能感受到,这种工具带来的不是“理论上能提升效率”,而是让你在本地写完代码后,顺手扫一遍都觉得不麻烦。

先把它装上:

pip install ruff

在项目根目录直接运行检查命令:

ruff check .

很多人第一次跑会看到类似的输出:

F401 `json` imported but unused
I001 Import block is un-sorted or un-formatted
UP035 `typing.List` is deprecated, use `list` instead

这几个提示都很有代表性:没用的 import、import 顺序混乱、使用了旧版语法。单独看都不是什么大事故,但代码库一旦庞大起来,这些边角料会越积越多,最后 code review 的时候看着就别扭。

举个例子,下面这段代码在团队协作中太常见了:

import os
import json
from typing import List
import sys

def load_users(path: str) -> List[str]:
    with open(path, "r", encoding="utf-8") as f:
        return [line.strip() for line in f if line.strip()]

代码能跑,功能上也没毛病。但 Ruff 一扫,至少能看出两个问题:osjsonsys 里有没被使用的模块,而 List[str] 这种写法在新版本的 Python 里也没必要再保留了。

想让 Ruff 直接修复这类问题,可以加上 --fix 参数:

ruff check . --fix

它会自动处理一部分机械性的修改。修复后,上面的代码大概会变成这样:

def load_users(path: str) -> list[str]:
    with open(path, "r", encoding="utf-8") as f:
        return [line.strip() for line in f if line.strip()]

这种感觉就很对路。它不是在教你如何写代码,而是先把这些不值钱但又碍眼的小问题清理出去,不占用你的思维带宽。

更进一步,Ruff 现在连代码格式化的活儿也能干了:

ruff format .

比如你临时写了一段脚本,功能没问题,但排版确实有点乱:

def build_payload(order_id,user_id,items):
    return {"order_id":order_id,"user_id":user_id,"items":[{"sku":i["sku"],"num":i["num"]} for i in items if i["num"] > 0]}

让 Ruff 格式化之后,代码的清晰度立马提升:

def build_payload(order_id, user_id, items):
    return {
        "order_id": order_id,
        "user_id": user_id,
        "items": [
            {"sku": i["sku"], "num": i["num"]}
            for i in items
            if i["num"] > 0
        ],
    }

这类工作以前通常交给 Black。现在 Ruff 也能胜任,至少在不少项目里,工具链确实可以再精简一层。

我的建议是,刚开始使用时别贪多求全,先把规则收紧到你真正会用到的那几类。在 pyproject.toml 里进行如下配置就够用了:

[tool.ruff]
line-length = 100
target-version = "py311"

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]
ignore = ["E501"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

这些规则代号不用死记硬背。大概知道它们的职责范围就行:

  • E/F 系列检查基础代码问题。
  • I 负责 import 排序和整理。
  • UP 会提醒你不要再写旧版本的语法。
  • B 则会揪出一些容易埋坑的 Bug 类写法。

例如下面这段代码,我在线上脚本里见过不止一次:

def append_log(msg, bucket=[]):
    bucket.append(msg)
    return bucket

新手喜欢这么写,老手忙起来也可能顺手写出来。问题在于默认参数 bucket=[] 这个空列表在函数定义时就被创建,并且会在多次调用中被复用,导致日志会越加越乱。Ruff 对这类问题就不再是简单的“风格建议”了,它是在帮你拦截潜在的 Bug。

改成下面这样才更稳妥:

def append_log(msg, bucket=None):
    bucket = [] if bucket is None else bucket
    bucket.append(msg)
    return bucket

Ruff 真正发挥价值的场景,不是你写个小 demo 的时候。而是在项目人多、提交频繁、CI 流水线已经有点跑得慢的时候,用它会特别顺手。

本地开发时,你可以这样组合使用命令:

ruff check . --fix && ruff format .

在提交流程中,还可以通过 pre-commit 钩子来自动化检查。在 .pre-commit-config.yaml 中添加如下配置:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.11.0
    hooks:
      - id: ruff-check
        args: [--fix]
      - id: ruff-format

这样一来,很多低级问题在 commit 之前就被拦截掉了,review 的时候就不用再为“import 顺序不对”、“这个变量没用到”这类小事反复沟通,大幅提升 CI/CD 流程的效率。

说到底,Ruff 最值钱的地方,不在于它有多“神奇”。而在于它把 Python 项目里那一堆零碎、重复、机械、但又不得不做好的事情,整合得相当利索。速度快,接入简单,给出的结果也清晰直接。一个工具能做到这个程度,对于优化开发工作流来说,已经非常够用了。

至于它未来会不会把所有老牌工具都替代掉,我倒不急着下结论。但至少在不少中小型项目、内部脚本、甚至一部分服务端仓库里,Ruff 已经从“可以试试”变成了“早点用上,能省下很多碎片时间”。这东西一旦用顺手了,再回头去看那套东一榔头西一棒子的检查链路,是真的会觉得麻烦。如果你也在为项目代码规范和工具链效率发愁,不妨到 云栈社区 的开发者板块和大家交流一下实战心得。




上一篇:台积电CEO直言机器人“炫技”不可取,产业核心在于AI芯片与传感器
下一篇:自除数算法题怎么解?从裁员热点到Python代码的清晰思路
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-24 22:45 , Processed in 0.802078 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表