PyCon 2018 之 Django 专题与 未来的包管理工具 pipenv

0x00 前言

PyCon 2018 有很多精彩的演讲,今天的文章里,挑出 Django 的几篇演讲大致讲讲。

注意:为什么是大致讲讲呢?因为即便是你看了我的这篇文章,依然需要多下点功夫自己去看演讲,自己去查资料,自己去消化。我的这篇文章只不过是我看演讲查资料慢慢消化过程中的产物而已。

0x01 演讲 1 - Taking Django Async

本演讲其实就是为了推广 Django 的新库。django-channels

这个库从 2015 年首发,现在已经经过了三年的进程。应该算是相对成熟了。

这个库有什么不走寻常路的地方吗?答案是有的:

  1. 使得 Django 增加了异步协议,比如说 WebSocket 协议
  2. 使得 Django 可运行后台任务。

作为 v2 版本的核心开发,作者必然是要吐槽一下 v1 版本,然后推荐一下 v2 版本。

v1 版本的架构设计是这样的。

核心开发给出了这样的评价:

  1. 在 Python2.7 的时候,就只能这么搞了。
  2. 需要维护的东西太多
  3. 没有 asyncio support
  4. 搬砖时候一不小心容易砸到脚

TODO : 补充一些其他的缺点

异步与同步接口耦合

作者认为此并非长久之计。

v2 时候,

重写 75% 的代码

异步与同步接口分离

这么设计的话,需要解决接下来的一个问题,同步转异步,异步转同步。

比如,我访问 view, 实际上是 async 转 sync, 然后才能调用 django 相关的方法,接着返回响应内容的时候,我还需要 sync 转 async.
再比如,我使用 websocket, 访问一条数据,但 ORM 是 sync 的方法,我还是要 async 转 sync 再转 async

这个 async 和 sync 的相互转换应该怎么做呢?

于是,两个适配方法就诞生了:

  • sync_to_async : 接收一个 async 的 function, 使之 awaitable, 然后使之在后台线程里运行。
  • async_to_sync : 接收一个 awaitable 的 coroutine , 使之转化成一个同步的 function, 该 function 暂停你调用的当前的线程,跳转到包含 eventloop 的主线程执行完毕,然后跳转回来。

https://www.aeracode.org/2018/02/19/python-async-simplified/

WSGI 如何运行 async

ASGI 如何运行 A

这对 Django 意味着什么?

如何保持兼容性

0x02 演讲 2 - Beyond Django Basic

作为一名有一定经验的 Django 开发者,用快进的方式看完了这个演讲。毕竟,我已经不是 Django 新手了。

毕竟这篇演讲只是给那些学完 tutorial 的人

想深入了解 Django, 多刷几遍文档比什么都好。

嗯,就不介绍了。

0x03 演讲 3 - Introduction to TDD with Django && Intermediate testing with Django

本演讲主要内容是 TDD 测试和 Mock 的技巧。

建议熟手直接看演讲者的书吧,本视频本人仅仅匆匆倍速看了一遍,估计并没有超出他的书的范围。

简单介绍了以下内容

  • 单元测试和功能性测试
  • 通过 Selenium browser 进行自动化测试
  • unittest 标准库
  • Django models, views and templates
  • 测试前后端代码
  • 基于测试的重构
  • TDD workflow

地址如下

https://www.obeythetestinggoat.com/book/praise.harry.html

说说个人对测试和 TDD 测试的基本态度,我觉得测试是好事,适当的测试是可以提升代码质量和程序稳定性的。

说测试会降低开发速度的,八成是没有善用测试。如果测试拖慢了你的开发速度,只能说明没有进行合适的测试,比如对一些无关紧要的功能进行测试。

但,这篇演讲和配套资料很好,不过有些美中不足。 这里基本上都还在用 Django 的 MTV 这一套。

我反正是不用这一套了。这个年头流行 SPA 呀。

所以,我们这篇演讲指的关注的内容就变成如下内容了。

  • 单元测试和功能性测试
  • unittest 标准库
  • Django models
  • 基于测试的重构
  • TDD workflow

而且,对于 API 的测试,现在基本上流行 POSTMAN

用 POSTMAN 的优点就在于可以把参数缓存下来下次接着用。有个小技巧就是从 chrome 拷贝一下 curl 到 postman 中。非常好用。

既然流行 SPA, 那么本次有没有介绍开 API 的利器呢?

0x04 演讲 4 - API-Driven Django

嗯,Django + django-rest-framework 实在是开 WebAPI 的神器。

这篇演讲,算是普及了一下常识。并没有想象当中的深入。

想用 Django 和 DjangoRestFramework 搞事情的,可以过来看我这篇文章。

https://zhuanlan.zhihu.com/p/33903527

需要注意的是,本次 PyCon 中有很多人已经用上了 pipenv 了。

0x05 演讲 5 - pipenv 未来的 Python 包管理工具

Kenneth Reitz 出品,必属精品。

Python 打包历史

刚开始,我们是这样安装包的。

1
2
3
curl http://pypi.python.org/packages/alsdasdl/requests.tar.gz | tar zxf
cd requests/
python setup.py install

这个问题初看起来不是问题,但是随着你安装程序的增多就知道有多么痛苦了。

  1. 有的依赖库依赖别的库你怎么解决?比如 pandas 需要安装 numpy
  2. 有的依赖库依赖 c 库怎么办?比如 LXML
  3. 在 python2.6.5 下,如果我需要安装两个不同版本的 Django 开发不同的软件怎么办?难道只能动态复制文件到 site-packages 里面?

后来,我们是这样安装包的。

1
easy_install requests

我们可以直接从 pypi 进行安装了。但尼玛,为什么 easy_install 安装很 easy, 但是没有 easy_uninstall?

好,2010 年后,我们继续前进:

  • 可以通过 pip 替代 easy_install 了。
  • 可以通过 virtualenv 管理项目的依赖库了。虽然说,还是不能像 ruby gem 一样同时把多个版本的的软件装在同一个系统里。
  • 可以通过 requirements 锁依赖了。

但,其他编程语言社区分别出现了如下的包管理工具:

  • node -> yarn && npm , 有 lockfile
  • php -> composer , 有 lockfile
  • rust -> cargo , 有 lockfile
  • ruby -> bundler , 有 lockfile

而生命苦短一方居然

  • python -> pip && virtualenv/venv , 无 lockfile

PS: Python3.3 之后,默认可以直接使用 venv 模块,不需要再安装 virtualenv 了。但还是需要手动,并且用起来比较反直觉。

关于 requirements.txt

  • 如果你使用 pip freeze 来形成这个文件,则不直观,完全看不出来哪个依赖库依赖哪个依赖。
  • 如果你直接手动指定你所需要的库,比如 flask 的话,似乎又有些太直观了。

如果能有一个东西,既可以表示 freeze 的结果 (what you want),又可以表示你需要的库 (what you need). 就好了。

这当然可以考虑用两份 requirements 来解决。先安装 what you need 用来开发,然后 freeze 为 what you want 去部署。

当然,铺垫了这么多 K 神肯定是来介绍他的 pipenv 的。

比如说,我想查看,本项目的依赖库,直接 pipenv graph

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
coverage==4.5.1
fabric==2.0.1
- cryptography [required: >=1.1, installed: 2.2.2]
- asn1crypto [required: >=0.21.0, installed: 0.24.0]
- cffi [required: >=1.7, installed: 1.11.5]
- pycparser [required: Any, installed: 2.18]
- idna [required: >=2.1, installed: 2.6]
- six [required: >=1.4.1, installed: 1.11.0]
- invoke [required: <2.0,>=1.0, installed: 1.0.0]
- paramiko [required: >=2.4, installed: 2.4.1]
- bcrypt [required: >=3.1.3, installed: 3.1.4]
- cffi [required: >=1.1, installed: 1.11.5]
- pycparser [required: Any, installed: 2.18]
- six [required: >=1.4.1, installed: 1.11.0]
- cryptography [required: >=1.5, installed: 2.2.2]
- asn1crypto [required: >=0.21.0, installed: 0.24.0]
- cffi [required: >=1.7, installed: 1.11.5]
- pycparser [required: Any, installed: 2.18]
- idna [required: >=2.1, installed: 2.6]
- six [required: >=1.4.1, installed: 1.11.0]
- pyasn1 [required: >=0.1.7, installed: 0.4.2]
- pynacl [required: >=1.0.1, installed: 1.2.1]
- cffi [required: >=1.4.1, installed: 1.11.5]
- pycparser [required: Any, installed: 2.18]
- six [required: Any, installed: 1.11.0]
flake8==3.5.0
- mccabe [required: >=0.6.0,<0.7.0, installed: 0.6.1]
- pycodestyle [required: <2.4.0,>=2.0.0, installed: 2.3.1]
- pyflakes [required: >=1.5.0,<1.7.0, installed: 1.6.0]
# 其他省略

如何尝鲜?我最近更新到了之前写的一个库(代码写的惨不忍赌,最近准备重构)

1
2
3
4
5
6
git clone git@github.com:twocucao/YaPyLib.git
cd YaPyLib/
brew install pipenv
pipenv --three
pipenv install --dev
pipenv shell

至于其他的功能,参考官网自己摸索吧。

在用 npm 和 yarn 的时候,我有这么一个想法,希望 python 圈子里面能出一个类似于包管理工具。今年 2 月份的时候把自己的项目迁移过来,发现 pipenv 用起来很挺舒服的。

pipenv 是未来。火速用上吧。

0xEE 参考链接


ChangeLog:

  • 2018-03-09 重修文字