尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

python pre-commit

python pre-commit # 聊聊Python项目里的pre-commit它到底是什么让我先说说pre-commit的本质。这玩意儿就像是你在提交代码前设置的一道安检门。我记得刚入行那会儿团队里总有人提交乱七八糟的代码——有的是忘了格式化有的是混入了调试用的print还有的甚至带着语法错误就push上去了。那时候的解决方案很简单谁出问题谁负责修但效率实在太低。pre-commit这个工具其实是一个钩子管理框架。用Git的人都熟悉hooks这个概念就是那些放在.git/hooks目录下的脚本。pre-commit工具做的事情很简单它接管了pre-commit这个hook让你用配置文件的方式定义在提交代码前要执行哪些检查。本质上说它把你那些需要手动检查的东西自动化了。举个例子我早期参与的一个项目代码审查里大概有30%的评论都是在说“这个函数没加docstring”、“这个地方缩进不对”、“这个import没按规范排序”。引入pre-commit之后这些问题在提交前就被拦截了审查的效率提升了一大截。它能做什么pre-commit能做的事情其实取决于你配置了哪些钩子。我见过最典型的使用场景包括代码风格检查。这个是最常见的比如用black格式化代码用isort整理import顺序用flake8或者pylint检查潜在的代码问题。说实话这些东西手动做很烦但机器做起来分分钟的事。文件格式检查。比如检查JSON、YAML文件是不是合法的格式检查Markdown文件是不是有语法问题。我有次在生产环境上因为在配置文件里写了个非法的YAML导致整个应用启动失败从那以后我就把这检查加上了。敏感信息检查。这个挺实用的——检查git diff里有没有包含密码、API key之类的敏感信息。很多人会在代码里不小心提交真实密码尤其是那些配置文件。还有一些跟语言无关的检查比如检查尾随空格、检查文件末尾有没有换行、检查是不是用了AWS STS临时凭证等等。这些细节单独看可能不痛不痒但累积起来对项目整洁度的提升很明显。怎么使用安装pre-commit其实挺简单的一行pip install pre-commit就行。然后你需要在项目根目录创建一个.pre-commit-config.yaml文件配置你想要的钩子。我一般会这样配置repos:-repo:https://github.com/pre-commit/pre-commit-hooksrev:v4.4.0hooks:-id:trailing-whitespace-id:end-of-file-fixer-id:check-yaml-id:check-added-large-files-id:detect-private-key-repo:https://github.com/psf/blackrev:23.3.0hooks:-id:black-repo:https://github.com/PyCQA/flake8rev:6.0.0hooks:-id:flake8配置好之后运行pre-commit installpre-commit就会把钩子安装到你的项目里。之后每次你执行git commit这些钩子就会自动运行。有一个细节值得注意对于第一次配置的项目最好先手动跑一次pre-commit run --all-files把全量代码的检查一遍免得第一次提交时因为历史遗留问题而失败。否则第一次提交就可能因为之前的不规范代码被卡住体验不太好。最佳实践根据我这些年的经验有几个点我觉得值得注意第一个是hook的选择要克制。很多团队一上来就配二三十个hook结果每次commit都要等半天。我的建议是选择那些对项目真正有价值的hook其他的可以省略。比如如果你的项目根本不涉及YAML文件就没必要配置YAML检查。第二个是利用好stages参数。pre-commit不仅支持pre-commit钩子还支持pre-push、commit-msg等其他阶段。我习惯把一些耗时的检查比如运行全部单元测试放到pre-push里而不是在pre-commit阶段就跑。第三个是考虑使用args参数来调整hook的行为。比如black默认的行长是88字符但有些项目可能希望用别的值。这时候可以用args来覆盖默认设置。第四个是处理好hook的缓存。pre-commit会在.pre-commit/cache里缓存hook环境但如果你的项目版本迭代很快最好定期清理这个缓存避免版本冲突。还有一个容易被忽略的点团队成员之间保持一致的pre-commit配置。最好把.pre-commit-config.yaml和.pre-commit-hooks.yaml都纳入版本控制这样新成员clone项目后就能直接使用。和其他工具的对比市面上还有其他类似的工具比如husky主要用于Node.jsgit-hooks还有每个语言自带的lint工具。相比huskypre-commit的优势在于它是语言无关的同一个配置文件可以管理Python、JavaScript、Markdown等各种类型文件的检查。如果你做的是一个全栈项目用pre-commit会比较省心。但husky在JavaScript生态里更深入跟ESLint、Prettier这些工具的集成更顺畅。至于直接写git hooks脚本pre-commit最大的好处是解决了hook的管理和分发问题。手动写hook脚本意味着每个开发者都要自己去维护这些脚本而pre-commit把这些统一管理起来了。从另一个角度看pre-commit和CI/CD工具的区别也挺大。CI/CD是在代码推送后检查pre-commit是在提交前拦截。两者其实互补pre-commit负责快速响应、本地检查CI/CD负责更全面的远程检查。我一直觉得理想的工作流应该是本地通过pre-commit的初步检查然后推送到CI/CD做更深入的测试。最后说句实在话pre-commit不是银弹。有些团队过度依赖它减少了代码审查的注意力。但在我看来pre-commit应该解决的是那些机械性的、可自动化的问题而代码审查应该聚焦在业务逻辑、架构设计这些机器难以判断的事情上。两者分工明确项目质量才能真正上去。
返回列表