Python 项目工程实践
动态语言一时爽,代码重构火葬场
随着公司产品周期迭代和业务发展,使用 python 这种动态语言开发慢慢也暴露出一些问题,比如性能低、易出错、难重构、难维护等。 网上大部分是技术相关文章,工程相关的比较少。笔者就之前几年写 python 和维护 python 后端项目的经验简单介绍下如何提升 python 项目工程质量。
背景
很多创业公司初期为了市场竞争,产品快速迭代,使用了 python,ruby 之类的动态语言开发,动态语言的优势在于表达能力强,比较灵活,初期开发的时候速度比较快。如果公司顺利活下来,之后产品会更加注重性能、稳定性等,这个时候动态语言的缺点也开始慢慢暴露起来。有时候换语言和架构的成本是巨大的,而且很多场景也没必要更换(比如 Instagram 一直用的 python,都优化到了解释器级别,当然国内大部分公司没这个能力),我们尽量通过工程手段来控制项目质量,对动态语言扬长避短,更愉快地做项目。
知乎为什么继续用 python
出于以下几点原因吧:
- 历史遗留问题,大量 python 项目
- 写起来爽,做业务初期开发速度快
- 基础设施支持比较完善
- 有不少懂 python 的程序员
- 大部分项目 IO 密集,初期使用 python 不会遇到性能问题
目前来看只有少数非常吃性能的项目用 golang 重写(golang 在并发和工程上非常不错),大部分场景 Python 够用,而且有时候新项目老板给的时间太短,换个技术栈还真不一定快速把业务做出来(少加班)
为什么要重视代码和工程质量
笔者这几年经历过各种 python 项目,见识过很多 python 程序员。之前维护过一些比较难以上手的代码仓库(无文档、无注释、无规范、风格混乱)等,深知一个恶心的代码仓库多么要人命。 实际上当初写 python web 入坑指南 并不是出于什么高尚的目的,只是实在受不了难以维护的 python 项目,把很多问题都总结了一下。
- 方便新手和团队其他成员快速熟悉代码
- 减少 bug,降低在修 bug 上的时间浪费
- 方便业务快速迭代,兼顾开发效率(减少无意义加班吧)
很多时候一开始写代码只是很小一块,后来维护、修改 bug、增加新需求等,如果代码写得糙,后期修改成本就会很高。
动态语言做工程的缺点
主要有以下一些问题:
- 解释性语言执行效率低,大部分时间用在 IO 密集场景,比如 web 后端
- 开发工具支持不够完善,不如 java 有那么完善的 IDE
- 难以重构。基本上重构只能依据字符串匹配,老实说每次重构有稍微大一些的改动都会有点担心
- 滥用动态特性导致代码不好维护。这是个双刃剑,但是对工程来说还是不要滥用
- 没有类型声明,看不出一些复杂类型的数据结构(Python、php 都在不遗余力地加上 type hint)
- 缺少一些最佳实践(技术、小白文章偏多,工程实践文章比较少)
笔者当时选择去做 python 后端也是因为比较喜欢 python 语言,轮子多、生产力高、写起来爽等,但是一旦开始真正项目协作的时候,很多问题也必须要重视(不仅仅是技术问题)。 下面从开发环境、工具、流程、规范等问题上总结下如何提升工程质量吧。
开发环境
最好统一每个开发人员的开发环境,当然我们不能强制要求所有人都用一样的操作系统和编辑器、IDE 等,但是有些小问题还是比较麻烦的,比如不同系统的编码、编辑器的 tab 空格、自动换行等。笔者当初实习的时候团队里所有人都是登录到服务器上用 vim 写代码的,环境比较统一,现在基本大家都是 mac,一致的环境。当团队每个人用不同的工具的时候,可以采用以下一些工具来构建统一开发和编辑环境。
- EditorConfig: 用来统一编辑器配置。如果成员用不同的操作系统和编辑器,建议使用。尤其是对于
python 这种使用缩进的语言。需要编辑器安装相应的插件,并且配置一个共同的配置文件加入到版本库(可以配置编码、缩进等) - Vagrant: 一款用于构建及配置虚拟开发环境的软件,基于Ruby, 主要以命令行的方式运行(没实战过)
- buildout: 知乎在用,把依赖包等安装到当前项目下。这样可以不用 virtualenv 之类的环境
- pienv/virtualenv: 构建 python 虚拟环境,之前没用 buildout 之前都是使用 virtualenv 构建本地开发环境
- cookiecutter: 项目模板生成工具,每个项目最好用统一的模板生成,防止各个项目都是不同的风格,同时也能快速启动新项目。(知乎内部有自己的生成模板)
开发规范
一般来说都是遵守 pep8,适当放宽下行长度限制,比如 120 列。如果有成员不使用 IDE,应当在其编辑器里加上对应的 pep8
检测插件。
- autopep8: 可以集成在很多开发工具里,尽量都用工具来格式化,避免风格不一致的问题。
- isort: 整理 python 包导入顺序,支持自定义配置,不用每次都费劲想着如何按照 pep8 顺序导入
- pylint: 静态检测,能检测出很多代码缺陷和不合规范的地方,笔者强烈推荐。最好集成到 CI 构建工具里。默认的 pylint
检测过于严格,我们可以自定义忽略一些提示,可以参考这个 pylintrc 文件
我个人的想法就是尽量能用工具做的就不要让人去做,工具能保证风格统一,减少出错可能,让我们把更多精力放在业务逻辑而不是调整格式上。项目大了以后代码的格式和排版等是很能影响开发心情的。笔者个人用的是 vim 的 python-mode 插件,基本上这些工具都支持,笔者写代码的时候格式也比较随意,只是改完文件后执行下 autopep8 和 isort,一切就又整洁了(类似于 golang 的 gofmt)。感兴趣的可以自己试试。
开发工具
这个之前总结过很多用过的工具,感兴趣的看看 开发和编程工具
开发流程
很多公司慢慢把版本控制迁移到了 git,使用 gitlab 管理代码项目。一般我们的 git 开发流程是这样的:
- fork 一份代码仓库
- 本地新建代码分支开发新功能、修 bug 等
- 开发完成后提交 merge request,有其他成员进行 code review。注意 commit 信息不能太随意,一般我们有一些提交模板
- 确认代码没问题合并到主干,每次构建都会执行单测、pylint 检测等
基本上这套 git 工作流程比较简单,目前也出过什么大问题。
总结
每种语言都有自己的优势劣势,适用场景,通过规范、流程、工具等尽量提升我们的开发、协作效率、工程质量,争取更愉快地开发,减少无意义的加班。
Life is short, You need Python