outline

本文包括以下内容:outline

django: 一个搭建后端服务的工具箱。framework: django vs flask/tornado/spring/laravel

restful: django/restframework/swagger

worker: django/uwsgi/gevent/celery/channels

database: django/mysql/sqlite/migrations

python: 一门依赖开发者的语言。developing: gitlab/pipenv/docker

quality: unittest/pytest/flake8/pylint/yapf

deploy: fabric/aws/nginx

conclusion

django

django 是一个大名鼎鼎的后端开发框架,

它自己的口号是 the web framework for perfectionists with deadlines.

在我用 django 开发的这几年来,

我觉得它是一个逻辑上自洽,

并且为了逻辑自洽甚至舍弃了一部分功能的框架。

frameworksearch google for django vs

讲框架避免不了的是同行竞争,

比如到网上搜一下 django vs ... 就有一大堆搜索结果。

其实框架之间的比较是很难的,

每种框架都有自己适合的业务场景。

xkcd-927: standards

django 最大的特点就是 Model 是一等公民。

在 django 中的所有的操作都会跟 Model 相关,

比如它提供了自带的强大 ORM,

也有一系列挂载在 Model 上的校验等。

个人感觉在项目的业务需求达到了某种程度的多样化以后,

基础框架用什么并不重要,

适合开发团队才是最重要的。

鉴于本文的标题是 django,

所以我们只讲 django。

restful

我参与的项目基本都是前后端分离的项目,

后端提供的接口都是用 djangorestframework 写的。

虽然像 HATEOAS 这样的高级属性还没用到,

但接口是遵循 restful 风格的,

比如像用 http method+status 表达语义,

对资源的定义等。

接口文档我们选用了 drf-yasg 来生成符合 swagger 规范的文档。

曾经我们也试过 django-rest-swagger 这个库,不过……

another help-wanted project...

使用现成框架的好处是语言表达力极强,

最终我们实现一个“解密微信提供的手机号”接口的伪业务代码大概如下:

class WeChatVS(BaseVS):

@with_response(empty=True)

@with_request(DecryptionSiri)

@action(methods=['post'], detail=True, url_path='decryption/phone')

def decrypt_wechat_phone(self, request, uid):

""" 解密并修改用户的手机号- https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html"""

self.check_account_request(request, uid)

openid, encrypted_data, initial_vector = self.request_data

phone = WeChatManager(openid).decrypt_safely(encrypted_data, initial_vector)

# TODO(ldsink): 找产品问一下外国手机号怎么处理

hutils.check_error(not hutils.is_chinese_phone(phone), 'o(╥﹏╥)o 目前只支持国内的手机号')

self.account.modify(phone=phone)

return self.empty_response()

这样的十行代码包含了文档、外链、错误检查、写库,

让写业务代码本身也有种施法的快感。

worker

最开始服务器上我们跑的是 django+uwsgi 的普通模式,

用 wrk 去压一个小接口,

测试环境 4G 内存的机器 QPS 只有 40 左右。

后来加上了 gevent, monkey patch 一下,改到了协程模式

同样的接口同样的机器 QPS 上升到了大概 600。

调优一下效果会更好。

(需要更高性能的业务可能就根本不用 python 了 Orz)

celery 充当了我们的定时任务+异步任务框架,

我们也拆分了 读写密集型/计算密集型 的两类队列以处理不同的事情。

对于业务中的即时通知部分,

我们用了 channels 库来实现 web socket 的功能。

对于这些大型的框架,其实我们选择余地并不大。

比如虽然 django 开发者有说在 3.0 会考虑大幅度重写异步调用,

channels 项目会逐渐弃坑……

但毕竟 perfectionists with deadlines.

不能说人家功能不完美,我们就不干活了嘛...

database

我们用到的数据库也是 mysql/mongo/redis 这御三家,

所以就是每个选取对应的连接库就是了。

值得一提的是在单元测试里,

我们用 sqlite(in-memory) 替代了 mysql 数据库。

sqlite 里缺失了 mysql 的函数的问题,

也可以用 connection.create_function 的方法来规避掉。

在上线时,还有一个很好玩的东西是 database migration,

这个基本上跟“给行驶中的火车换轮子”一样刺激。

详细的细节以后会专门开篇文章讲一下(挖坑预警),

从结果上来说我们做到的是利用 Django Migration 做到数据库结构变更全兼容。

python

上面一小节中,我们基本上是走马观花地过完了 django 相关的三方库。

到了真正用 python 开发的时候,

我们遇到的更多的是框架之外的奇遇。

每门语言都有自己的味道。

我很喜欢 python 的一点是:

这门语言有着非常强的表达张力。

就像上面举的那段典型业务代码一样,

在实际的开发中,

python 是能完美表达开发者心中所想的。

但假如开发者自己都没想清楚自己要写啥,

这就有点不妙了。

所以我们有一系列的开发工具来保持清醒。

quality贺师俊在《如何引导程序员新人按正确的流程开发?》下面一段我很欣赏的回答

除了开发流程上的类似要求,

我们对代码本身也执行了类似的严格要求:单元测试覆盖率必须得在 96% 以上 (unittest/pytest/coverage)

代码的逗号、换行、引号的使用都必须符合规范 (flake8)

代码强制经过 linter 检验,禁止多种黑魔法 (pylint)代码的各个模块之间必须符合特定的拓扑顺序 (pylint-topology)

代码风格(如字典的复制、长列表、换行与空行)强制统一 (yapf)

其中单元测试覆盖率必须得在 96% 以上值得被单独拎出来表扬一下。

业务代码的 96% 的覆盖率是什么概念呢?

这意味着代码里只有那种真正的边缘情况是没被测到的。

(比如为了兼容微信 SYSTEM ERROR -1000 写的代码)

为了达到了这么高的覆盖率,

我们也专门强化过单元测试的表达力,

比如一段测试创建用户接口的伪代码可能如下:

def test_create_account(self):

""" 测试创建用户 """

with self.assert_model_increase(Account, delta=1):

response = self.client.post(self.account_url(), {'username': 'hulucc'})

self.ok(response, username='hulucc', tags__length=0)

with self.assert_model_increase(Account, delta=0):

response = self.client.post(self.account_url(), {'username': 'hulucc'})

self.bad_request(response, message=AccountErrors.DUPLICATE.value)

所有这些限制都在 CI 中检查了,不通过的话是不让 merge into master 的

developing

我们的合作方式是用 gitlab 作为代码托管平台。

为了团队的开发效率,

我们还自己写了个小机器人来处理各种如分支合并、有效性检查、贴标签之类的杂活。

gitlab ci 不仅被用来做开发阶段的质量保证,

最终我们的构建上线也走的是 gitlab ci (以前我们用的是 jenkins)

对于 python 的依赖管理,

我们用的是 pipenv,

pip list 一下大概有了 181 个库。

(关于 pipenv 的介绍可以参见《Python 依赖管理的未来 - ldsink》)

也因为我们线上用的是 docker,

所以不想装依赖的也可以直接用 docker 的环境开发。

deploy

部署这一块我们暂时还没上 k8s,

目前走的是 gitlab ci 中调用 fabric + aws(boto3) 直接操作裸 docker 的方式。

aws 的负载均衡器提供了基础的流量切换服务,

我们也是借用了现成的服务达到灰度发布、无缝发布的效果。用 GitLab CI 部署的步骤图

conclusion

至此,本文介绍了一遍我们在 Python 业务后端的实践。

对于高可用、容器化、数据库等屠龙技,

业界其实有非常多的探讨,

大家也很容易找到现成的文章。

但具体到业务后端的工程化实践,

能借鉴的大型项目并不多。

我读过的也只有两年前的 reddit 代码跟 sentry 这个 django 项目符合要求了。

总的来说,我们用 django 在开发中遵循的约定跟共识有这些:做正确的事情。比如我们在讨论过后,一致觉得“线性的 Commit 历史是最干净的”,从当天开始我们的 Commit 历史就是干净的线性历史了。

自动化一切能自动化的工作。用 swagger 自动化生成文档,用 gitlab ci 自动化质量保证。

尽可能使用最新的特性,让代码时刻保持崭新。我们每隔一阵就会把所有依赖升到最新的稳定版。

不过因为这个我们也踩了不少坑。

不少时候三方库会引入全新的用法,动辄改动 100+ 的文件数。

这个时候就到了 Vim Macro 展现魔法的时候了。

假如你也在用 Django 作为后端框架的话,

不防尝试一下上面提到的各类工具,

绝对物超所值噢 :)

原文链接,作者 @苏子岳

本文版权属于再惠研发团队,欢迎转载,转载请保留出处。

python 软件工程_软件工程实践之 django/python相关推荐

  1. python 软件工程,软件工程实践之 django/python | 码农网

    软件工程实践系列文章, 会着重讲述实际的工程项目中是如何协作开发软件的. 本文主要介绍了 django/python 系列的 工具 链. outline 本文包括以下内容: outline djang ...

  2. pycharm python部署_使用PyCharm配合部署Python的Django框架的配置纪实

    安装软件安装 Python 2.7.PyCharm.pip(Python包管理工具).Django ( pip install Django) 部署PyCharm 新建Django工程 完成后,其目录 ...

  3. 零基础自学python计划_「经验分享」python零基础学习规划与建议!

    如果你选择了自学,我想给你提几点建议: 1.找浅显易懂,例程比较好的教程,从头到尾看下去.不要看很多本,专注于一本.把里面的例程都手打一遍,搞懂为什么. 2.去找实际项目练手.最好是要有真实的项目做. ...

  4. 零基础学python 视频_零基础入门学习PYTHON(第2版)(微课视频版)

    小甲鱼畅销图书重磅升级,针对Python 3.7,通过生动的实例,让读者在实践中理解概念,在轻松.愉快中学会Python! 本书提倡理解为主,应用为王.因此,只要有可能,小甲鱼(注:作者)都会通过生动 ...

  5. 六星教育python怎么样_六星教育:Python怎么学?自学Python经验分享

    近些年,随着人工智能.大数据.自动化运维等行业的兴起,Python在编程方向上得天独厚的优势也凸显出来.随着Python工程师需求的日益增多,Python薪资也随之水涨船高.学习Python的同学越来 ...

  6. 教孩子学python 豆瓣_你是如何自学 Python 的?

    Python我第一次听说的时候, 觉得不错, 毕竟代码缩进的很规范. 我以前很想学python的, 只是除了加减乘除在IDLE里弄完了之后, 觉得没什么意思, 就卸载了. 装了, 卸载, 后来再装, ...

  7. python编程入门到实践 百度云-python网络爬虫从入门到实践pdf

    python网络爬虫从入门到实践pdf是一本非常热门的编程教学.这本书籍详细讲解了Python以及网络爬虫相关知识,非常适合新手阅读,需要的用户自行下载吧. Python网络爬虫从入门到实践电子书介绍 ...

  8. 头条上python广告_满大街都是Python广告,真的如广告说的那样方便吗?,学精通后真能月如过万吗?业内大佬怎么看?...

    在编程领域.Python语言已经被吹得神乎其神.很多人已经产生了一种错觉:仿佛当今编程世界,唯Python莫属,其它语言皆为渣渣. 就连地产大佬潘石屹也发微博为Python背书,不愧两者都姓" ...

  9. python+[:]+切片_我从C ++到Python的方式:概念上的改变

    python+[:]+切片 by asya f 由asya f 我从C ++到Python的方式:概念上的改变 (How I went from C++ to Python: a conceptual ...

最新文章

  1. pytest框架安装(MacOS)
  2. 遗传算法解决TSP问题 Python实现【160行以内代码】
  3. 深度linux安装spotify,如何在 Linux 上使用 snap 安装 Spotify(声破天)
  4. 虚拟化精华问答 | 怎样使虚拟机能够达到比较高的IO性能?
  5. 3D Computer Grapihcs Using OpenGL - 18 相机移动
  6. 首批共享单车死于 2019
  7. 请简要概括linux与windows在文件系统方面存在的不同点,简要回答下列与网络操作系统、网络安全和数据存储相关的问题,将解答填入答题纸对应栏内。br 【问题1】(10分)br (a)Win...
  8. 总结全网最全的数据学习平台
  9. CDA备考学习学习笔记——基础知识篇(一)
  10. 关于网络超时时间那些事
  11. html5转ipk,OpenWrt更新ipk教程
  12. JSP打印九九乘法表和表格
  13. linux下scp的常见问题解决方法
  14. python学习记录——容器篇
  15. 2013.6甲骨文公司的电话面试
  16. hash值和history值详解区别
  17. xp局域网内共享设置
  18. 【翻译大老外的文】信息平台与数据科学的兴起
  19. 转载 NLS_LANG设置
  20. 【IntelliJ IDEA的简介】

热门文章

  1. shell常用命令大全及注意事项
  2. 虚拟机修改服务器mac地址,虚拟机修改服务器mac地址
  3. python对双目摄像头进行左右图像分割保存
  4. java web 项目 常用 小工具类 ~~~~
  5. 老闪创业那些事儿(12)——产品经理小P的一天
  6. h5 meta标签大全
  7. Python基础知识3:函数、三元函数、lambda函数
  8. 个人笔记-List遍历一(遍历及修改)
  9. baresip android 编译、运行教程2 :视频通话
  10. 最新最好的八款渗透测试工具