在前面关于Backbone的文章里提到过要谈后端的,现在就来简单说说在那个离线客户端的后端实现中用到的一些东西。
用了很长时间的web.py,之所以选择web.py,是走过很多弯路的。早年主要是一些重量级框架,接触过Django、TurboGears和Pylons相当长时间,尤其是TG1用了很久,具体在《SD2C之三种Python的Web框架 》里说过。后来还有一段时间用了web2py——因为它是all in one。但后来发现这类重量级的框架太笨重,安装部署都麻烦,最关键的是局限性太大——且不说Django/web2py这种,全要按它们的路子走,TG1换了模板和ORM,有些功能也没了,Pylons则是换起来麻烦。于是转向轻量级的框架。
当时也没太多研究,就大致看了一下,感觉web.py比较简单,而且资源也挺丰富,就用起来了。关于web框架的选择,我曾经零散谈过几次,主要的理由有几个:
首先是轻量。重量级的框架实在是用烦了,所有的功能都要按它们设定的路子走,稍有不慎就掉坑里。除此之外还有个问题就是,它们各自的实现都不一样,一但需要切换,原来的经验全部作废,这是我不能接受的——年纪大了,从头学新东西太费事。
其次是要易学易用易部署。易学需要有简单全面的文档,各种资源相对丰富。易用是基本的功能要能简单实现——比如REST。易部署……这个只要是WSGI现在用gunicorn都容易,没什么好说的,但还有一点很关键的是尽量不要有我不认识的外部依赖。
第三就是我现在比较熟悉的SQLAlchemy和Mako模板能直接用上,我可不想再学别的ORM和模板了。
最后则是一些小原因:比如Django这种名字不好读的我就不太喜欢。还有像Flask和uliweb依赖的那个Werk什么什么的,那名字我不搜索从来就没法正确拼出,更不要说读了。
这几个条件一出,常见的web框架大部分都被毙了:Django太重,名字不好,没法简单地换掉模板和ORM。TurboGears/Pylons/Pyramid外部依赖太多。web2py局限太大,模板和ORM都没法换。flask/uliweb依赖那个我很不喜欢的Werk什么什么。Tornado之类的异步框架太不易学。于是就剩下web.py和bottle。而选择web.py完全是因为先入为主。
因为之前用了TG1很长时间,有些功能用着挺习惯,所以也在web.py下也自己打造了一堆类似的东西,于是有了这个webpyext(起初把它叫做webtg)。
使用方法参见前面的《Backbone笔记之三(Controller与集成) 》里的例子程序(注意:仅限目前的版本,以后计划改用bottle)。
这个项目已经发布在bitbucket——除了fork或依赖在github上现有的项目会放在github上以外,我自己创建的项目都放在bitbucket:
https://bitbucket.org/raptorz/webpyext
(不过因为某些脑子被枪打过的家伙在领导着这个国家的互联网,所以目前在中国大陆境内访问 bitbucket.org 和 github.com 都不太顺畅,丫们真是中国技术创新最大的敌人,真不知道这两个分享源代码的网站哪里戳到丫们的G点了…)
当然,如这个项目的说明上所说,我已经改用bottle,所以这个项目以后可能都不会再更新,仅供参考,或者有兴趣的人可以自行fork继续。
选择bottle的理由其实与选择web.py一样:轻量、无依赖、简单易用。但是放弃web.py的理由有一个:Aaron去世了。目前看来暂时还没有谁要接手web.py的迹象,所以还是换了吧。
关于bottle与web.py的比较,可以看一下令狐虫的这篇《bottlepy及其它》。
当然,对我来说换到bottle也是有不少问题的。首先就是这些为web.py写的代码大部分用不上了,我需要按bottle的方式重写一套(这个工作正在进行中)。其次是bottle的某些方面功能比web.py更弱一些,比如没有session,比如plugin+route对象的方式不如web.py的processor+web.ctx方便好用。而且bottle的插件模型与自定义decorator有冲突,也就意味着你必须将所有自定义的处理都做成插件,然后插件之间的交互又成了新的问题。
不过有失有得,bottle的request不错,甚至包括了对json请求的支持,这样的话用作backbone后端就更省事了(web.py的话,我是在这个webpyext里做了一个decorator来处理的)。
还有一个选择bottle的次要原因是它的性能略好,详见《继续小测python web server 》。更多关于webserver性能方面的比较,可参见这个《Web Framework Benchmarks》。