Python之美
首发于Python之美
我的开源世界观

我的开源世界观

我是一个Python程序员,在Web开发中我会用到一大堆的开源项目,如Linux、Python、Emacs、Spacemacs、Httpie、Flask、Requests、Sentry、IPython、Pyramid、Mako、Oh My Zsh等等。无法想象没有它们,我该如何工作。

相信你看到上述列表中出现的项目名字,有些也很熟悉,甚至是经常和它们在打交道。

我们先看一个有趣的事情(2016-09-07):

其中,Django的贡献代码的人数1250,而Fork的数量是8509!!Flask的贡献者为346人,Fork数量为7108!!Star可以理解:欣赏这个项目,未来可能用到,方便检索,但是Fork了不贡献代码这是什么心态呢 (ÒωÓױ)?

很多人也会开源自己的项目,但是除了熟人和公司这样的纽带,一般很少可以看到其他人来提Pull Request或者Issue的。当然国人也不乏一些好的项目,比如结巴分词。但是大量的项目Star数量止步于1(因为自己可以给自己点呢!)。

我们看一下Github上目前Python社区中很火的一些项目国人的参与度。我写个一个小脚本cn_participation.py,通过 List contributorsGet a single userSearch repositories这3个Github API获取需要的数据。


国人的参与度的项目,选择的标准是Star数量超过3k,工作中常用。结果如下:

-----------------------------------------------------------------------
项目               	总贡献者	        中国贡献者
flask                	346     	7
django               	419     	0
requests             	415     	6
youtube-dl           	425     	5
ansible              	410     	1
virtualenv           	99      	1
pip                  	275     	6
sqlalchemy           	210     	2
mongoengine          	211     	9
django-rest-framework	422     	4
jinja                	130     	4
celery               	406     	5
rq                   	97      	6
wtforms              	66      	1
pelican              	278     	4
salt                 	371     	4
gunicorn             	197     	10
werkzeug             	192     	8
sentry               	267     	7
pytest               	198     	4
cython               	175     	0
compose              	196     	3
docker-py            	214     	6
pandas               	410     	2
redis-py             	120     	4
ipython              	451     	3
fabric               	118     	1
httpie               	55      	1
scrapy               	212     	4
tornado              	241     	22
cpython              	133     	1

这个数据不一定是正确的结果。因为Django和Ansible等项目的贡献者实际的数量都已经超过1k,但是Github API由于性能等原因做了缓存,且只能展示前500个贡献者(实际还上不够500)。其次我只是通过location字段中是否包含北京、上海、广州、深圳和China这几个词判断是否是国人,如果有些人没有添加位置信息,就会被忽略了。

限于篇幅,这里只列出了贡献2个或者更多项目的贡献者ID及其贡献的项目名字:

-----------------------------------------------------------------------
ID                   	贡献项目数	项目列表
lepture              	4       	wtforms werkzeug pandas tornado
dongweiming          	4       	pip celery ipython httpie
felixonmars          	3       	docker-py scrapy tornado
mozillazg            	3       	sqlalchemy jinja rq
irachex              	3       	gunicorn pytest docker-py
hrbonz               	2       	celery pelican
messense             	2       	requests sentry
s7v7nislands         	2       	requests gunicorn
keakon               	2       	gunicorn tornado
tonyseek             	2       	rq pelican
hongqn               	2       	pip gunicorn
pengfei-xue          	2       	flask requests
fengsp               	2       	flask jinja
wooparadog           	2       	gunicorn pytest
tolbkni              	2       	celery fabric
codeb2cc             	2       	celery tornado
wenchma              	2       	compose docker-py

这个结果有三点超出我的预期:

1. 很欣慰,国人的参与度还可以。

2. 列表中的用户ID有一半我之前并没有见过。

3. CPython中有一个中国的贡献者,ID为gumblex, 他也是结巴分词的主要贡献者。国人使用Python如此之多,却没有一个Python核心开发者。好桑心!

顺便想做个调查,为什么Github上Python语言Star数量第一的Httpie竟然只有我一个贡献者呢?是大家都不用么?

接着我们看看国人写的优秀项目的列表(只能抓到前一千个项目):

----------------------------------------------------------------------
项目                        	创建者   	        Star数
fxsjy/jieba                   	fxsjy       	5971
0x5e/wechat-deleted-friends   	0x5e        	4505
tangqiaoboy/iOSBlogCN         	tangqiaoboy 	3739
taobao/nginx-book             	taobao      	2833
programthink/zhao             	programthink	2404
darknessomi/musicbox          	darknessomi 	2063
douban/dpark                  	douban      	1857
waditu/tushare                	waditu      	1802
gnemoug/distribute_crawler    	gnemoug     	1715
sshwsfc/xadmin                	sshwsfc     	1707
mmin18/LayoutCast             	mmin18      	1581
eastlakeside/interpy-zh       	eastlakeside	1580

PS:其中有些项目并不是Python的,比如iOSBlogCN、zhao和nginx-book,有些是组织下的,比如dpark和interpy-zh。国人做的好的项目还是蛮少的。


BTW,你心目中的大神,有几个上榜了呢?

在我拟本文的时候,我找到了一篇玉伯写的《什么是开源精神》。这篇文章的2个主标题很好:

1. 在开源世界里,参与比主导更重要。

2. 开源的是社区,代码仅是很小的一部分。

无论是我现在的公司,还是之前的公司都不乏非常优秀的工程师,他们有想法并且会付诸行动。在和他们合作过程中会有惊喜,能碰撞出灵感,也会学到新的解决问题的方法和思路。他们有两个特点:「喜欢造轮子」和「对开源不热衷」。好像大家都爱写个Web框架啦,ORM啦,开发工具的插件啦...,对,有段时间还流行造WYSIWYG的富文本编辑器。说到这里好尴尬,因为在豆瓣2年多,我好像没有给项目引入什么额外的第三方库,也确实没有造过几个「轮子」,总体大概就是一件:做别人「轮子」的第二个使用者(第一个是作者本人),反馈甚至去提代码帮助改进。说到这里,解释下为啥我工作中「不热衷造轮子」。我明知道「造轮子」会让我更有地位和价值(因为除了我别人不懂啊,这是潜规则好吧-。-),但在团队内还是考虑大家的感受,不给其他同事添加用我的「轮子」的痛苦,除非我知道这个「轮子」足够好。

在2年前,我曾经写过一个Web框架,也是想要一个人搞定模板、WSGI、ORM等等。做着做着,我发现无法说服自己做的这个东西比现存的竞品的优势在哪里,也就没有坚持下来。对于当时的能力而言,我还做不出来一个有意义的「轮子」。

后来我开始阅读各种开源项目,看到好的项目Star一下甚至写博客宣传一下;尝试理解它们的设计思想;使用中遇到了问题又没有能力解决就去提Issue;有能力的时候,遇到Bug或者想添加功能我就自己去提PR。并不需要刻意,顺手而为罢了。

今天和大家聊聊我在完成《Python Web开发实战》这本书时和开源世界发生的故事,以及我对参与开源的一些看法。

aiglos

说出来你可能不信,一开始和编辑讨论书稿还是使用邮件。走的是「我写完了一章就把书稿用邮件发给编辑,编辑添加意见和修改再发给我,我再修改...」这样的循环。我当时有种「都什么年代了还用这么古老的方式」的感觉,不能忍。首先从网上找了下,确实没有合适的解决方案(要考虑编辑的技术能力),那写一个吧!大家先看看效果:

假如你学过Django,应该觉得好熟悉。对, 这是Django book 中文的翻版,样式是抄的,我只是把后端改成了Flask + SQLAlchemy + Mako,并且支持Markdown。这页面显然没有Material-UI之类的库做出来的东西酷炫好看,但是别忘了,这只是一个试水项目,需要糙、快、猛的验证需求就可以了,如果大家真的接受,我再优化也不晚。显然考虑对了,最后它还是被抛弃了,我和编辑改成用Google Drive完成日常讨论及修改。

gitbook-plugin-highlightt

在使用Gitbooks.io的和评审老师讨论的时候,一位评审老师建议如果是按行讲解,最好代码中显示出行号。但是Gitbook对于代码只支持语法高亮,还没有支持行号。编辑说他们转化格式的时候支持这样表达行号:

```python,numbered,start="1"
some stuff...
```

Gitbook是使用Javascript写的。我Javascript用得不好,但是觉得可以试试,就这样,一个周末下午的时间完成了这个插件,效果如下:

再下面的逐行讲解中就清楚多了:

有想法就付诸行动,哪怕最后没有完成,至少努力了。

saltstack/salt

由于salt贡献者已经超过了1.5k, 虽然我之前也改过一个小问题,但上面的列表中,我被无情的忽略了。我写书的时候全部库和软件基本都使用最新版,在用salt的过程中,发现一个错误。详情可见 Fix psutil.cpu_times unpack error by dongweiming · Pull Request #32182 。简单地说就是psutil在更新的时候修改了返回值的数量,造成使用它这个接口的项目都会出现这样的错误。

出现问题,是给你天天使用的项目贡献代码的最好机会,虽然大部分是其实是使用者用错了。

celery/celery

在我编写Celery对应章节的时候,遇到一个很偶遇的错误: Fix event result is None by dongweiming · Pull Request #3170 · celery/celery · GitHub

报错信息的格式好乱。

ipython/ipython

书中有专门的一节讲IPython,7月8日Matthias发布了IPython 5.0 LTS,我的内容随之调整,比如之前只是介绍prompt_toolkit,现在已经真的可以用了。在看5.0的whatsnew的时候,我发现它支持定制终端的颜色方案了。但是按照文档的提示,我终端颜色并不符合预期,一言不合,我就直接去翻源码了。然后就发现这个typo fix highlighting_style typo by dongweiming · Pull Request #9766

严格的是,这不是typo,而是错误。

Supervisor/supervisor

另一位评审老师建议我supervisor内容中加上和虚拟环境工具virtualenv一起用的例子。

我是这么写的:

之前的例子是在虚拟环境中实现的,如果Supervisor安装在全局而要使用虚拟环境,可以通过如下两种方法。                                                               
                                                                                                                                                               
1.  把program项中的command改成完整路径:                                                                                                                       
                                                                                                                                                               
    ```                                                                                                                                                        
    [program:app_chapter6]                                                                                                                                     
    command=%(ENV_HOME)s/.virtualenvs/venv/bin/gunicorn -w 3 chapter6.section1.app:app -b 0.0.0.0:9000                                                         
    ```                                                                                                                                                        
                                                                                                                                                               
2.  使用参数environment把全局环境目录放进PATH:                                                                                                                
                                                                                                                                                               
    ```                                                                                                                                                        
    [program:app_chapter6]                                                                                                                                     
    environment = PATH=%(ENV_HOME)s/.virtualenvs/venv/bin:%(ENV_PATH)s                                                                                         
    command=gunicorn -w 3 chapter6.section1.app:app -b 0.0.0.0:9000                                                                                            
    ```                                                            

supervisor支持environment参数,可以指定环境变量,那么第二种是不是看起来「没毛病」?

但事实上它是错误的(「这不科学啊」)。

我之前也给它贡献过代码,但是这次比较懒,因为调试很麻烦,当时又没有时间,所以先提了一个Issue Supervisor Issues 787,现在的维护者认可了这个问题却并没有想添加这样的支持。好吧,自己动手丰衣足食:Search for command using PATH from environment=. Fixes #787 by dongweiming · Pull Request #799,维护者会在下次发版的时候合并它。期待中...

注意哦,书中已经明确了这样的用法,然而PR还没合并呢,但是我有信心!

mattupstate/flask-security

Fix Mongo ValueError by dongweiming · Pull Request #534 · mattupstate/flask-security · GitHub 这个也是在写书中发现的问题,但是这个项目看起来属于没人维护状态,这个PR安静的躺在那里。但是不要感觉失望,因为这个PR是open状态,别人遇到这个问题就可以搜到。这也是一种对开源项目的贡献。

pallets/werkzeug

我书里面没有介绍到Flask-Cache,因为它基本依赖于werkzeug且一般项目不会使用多种缓存方式,我觉得实际工作中用这个插件意义不大。书中介绍了豆瓣使用的Memcached客户端libmc,我认为它应该是现存的客户端中被大型网站应用的最频繁和最快的选择了。werkzeug中并没有对应的支持,所以我去提了一个Issue Add libmc support · Issue #982untitaker并不反对,但是想把这部分重构一下,我最近终于闲下来,也在思考他提到的问题,如果你有好的想法,欢迎去回应。

和本书有关的部分就到这里了。但还没有结束。

-- 2016/09/26 更新 ---

pallets/flask

在勘误的时候,@MrCJJW提到了第3章 P34 自定义URL转换器 · Issue #9 · dongweiming/web_develop · GitHub。确实是一个Flask文档提示的误导,所以我就提了个 Fix unbound error by dongweiming · Pull Request #2039 · pallets/flask · GitHub,已经被合并。上面的脚本就不重跑了,只是一个docstring的修改。

开源对我的意义

有些人会问,开源对我们有什么意义呢?

1. 有一波大神给你做代码评审。如果你在公司写代码,就算是代码评审,由于情面性格等原因,大家一般不会说的太狠,你有错,别人也不会认真的说。但是在外面不是,大家都很直接的,整个过程你可看到的都是真相。

2. 学习一些工作中不能学到的东西。举个例子,pip commit e430b58cebff96#comments,那时候我真的不知道原来sorted可以对set类型的数据排序,涨了姿势。

3. 个人的意愿。我曾经给Celery修改过例子: Modify some examples by dongweiming · Pull Request #1851, Celery有很多有意思和有用的功能特性并不及时或者根本没有出现在官方文档中,如果你没有Watch这个项目经常关注或者去阅读它的代码,你是不会知道的。它迭代很快,但是有时候代码并不向前兼容。对于初学者,这些例子很可能是它接触Celery的第一步,Ta有可能因为例子跑不起来就放弃了。而对我来说,就是顺手的事。

我听过有人说:「他看不起用typo混进贡献者的人」,这些人动动嘴能力特别厉害,心胸也特别狭隘。我觉得我可以去知乎回答一个问题「人为什么可以如此狭隘?」。有一天,我看到我的timeline上,Gvanrossum(不知道他是谁我可真没有办法了)fork了Pyjion,我当时想「(⊙v⊙)嗯,这是什么节奏」。 等了一会发现Gvanrossum来提PR It's holistic (one ell) by gvanrossum · Pull Request #193。 Python作者出来改typo,这个事情太有必要拿出来看了,我要截图:


最后。用我非常喜欢的Bootstrap作者之一fat,在另外一个项目zoom.js上面留下的一句话来结束:

希望越来越多的人能来支持开源项目。

无耻的广告:《Python Web开发实战》上市了!

欢迎关注本人的微信公众号获取更多Python相关的内容(也可以直接搜索「Python之美」):

编辑于 2017-04-17

文章被以下专栏收录