Python Web开发中常用的第三方库

Thursday, November 28, 2013

Python Web开发中常用的第三方库

TL;DR

经常有朋友问,如果用Python来做Web开发,该选用什么框架?用Pyramid开发Web该选用怎样的组合等问题?在这里我将介绍一些Python Web开发中常用的第三方库。基本适用于Django以外的Web框架(Pyramid, Flask, Tornado, Web.py, Bottle等).

ORM

  • SQLAlchemy, 在ORM方面,首选SQLAlchemy,没有之一!
    支持SQLite, PostgreSQL, MySQL, Oracle, MS-SQL, Firebird, Sybase等主流关系数据库系统
    支持的Python环境有Python2、Python3,PyPy以及Jython。
    主要的特性请移步 Key Features of SQLAlchemy
    推荐和数据库迁移工具Alemic搭配使用

  • MongoEngine, 如果你用MongoDB,推荐MongoEngine.

Template Engine

在模板引擎方便选择也是比较多, 有ChameleonJinja2Mako等可供选择,用过ChameleonJinja2,性能都非常好.

Form Engine

Cache Engine & Session Store

  • Beaker 缓存和Session管理首选Beaker, 没有之一! 可以搭配文件、dbm、memcached、内存、数据库、NoSQL等作为存储后端. 如果你用Pyramid作为Web框架,那么可以直接使用pyramid_beaker.

Others

环境构建

任务队列

  • Celery (芹菜)一个分布式异步任务队列, 很强大!
  • RQ 这是一个轻量级的任务队列,基于Redis, 可以尝试一下。

WebServer

工具

  • Fabric, 可以通过它完成自动化部署和常规的运维等工作。《Fabric-让部署变得简单》_PPT
  • Supervisor 一个强大的进程管理工具,用来管理各种服务(比如Gunicorn、Celery等),服务挂掉时 Supervisor 会帮自动重启服务。

导出报表数据

  • Tablib,这个挺好用,支持导出Excel, JSON, YAML, HTML, TSV, CSV格式数据, 我创建了一个Pyramid插件可以集成到Pyramid项目中使用 pyramid_tablib
  • 导出PDF有reportlabPyPDF2

第三方身份验证

  • velruse, 支持各大网站的身份验证, 国内部分我已经加入了WeiboDoubanQQTaobaoRenren,并merge到主版本库中。欢迎使用!

Helper

To Be Continued...

升级PostgreSQL 9.2 -> 9.3

Thursday, November 14, 2013

PostgreSQL发布9.3了, brew upgrade postgresql 升级到9.3, 竟然启动不起来, 查看日志发现原来9.2的数据格式不兼容,需要迁移一下数据, 碰到这个问题的同学可以看一下 :-)

错误日志, 数据不兼容

/usr/local(master ) tail -f /usr/local/var/postgres/server.log
FATAL:  database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 9.2, which is not compatible with this version 9.3.1.

解决办法

PostgreSQL提供了一个升级迁移脚本 pg_upgrade, 用来迁移数据

pg_upgrade -b oldbindir -B newbindir -d olddatadir -D newdatadir [option...]

1. 新建一个PostgreSQL9.3的数据目录

/usr/local/var(master ) mv postgres postgres9.2
/usr/local/var(master ) initdb /usr/local/var/postgres -E utf8

2. 迁移数据到新目录中

/usr/local/var(master ) pg_upgrade \
-b /usr/local/Cellar/postgresql/9.2.4/bin/ \
-B /usr/local/Cellar/postgresql/9.3.1/bin/ \
-d /usr/local/var/postgres9.2 \
-D /usr/local/var/postgres \
-v

最后迁移完成打印下面的信息就代表迁移成功了

...
Creating script to analyze new cluster                      ok
Creating script to delete old cluster                       ok

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
    analyze_new_cluster.sh

Running this script will delete the old cluster's data files:
    delete_old_cluster.sh

3. 启动PostgreSQL9.3

查看版本和数据

/usr/local/var(master ) run_postgresql
server starting
/usr/local/var(master ) psql postgres
psql (9.3.1)
Type "help" for help.

postgres=# \l

4. 删除老版本和数据

删除数据和刚刚执行pg_upgrade产生的两个脚本

/usr/local/var(master ) rm -rf analyze_new_cluster.sh delete_old_cluster.sh postgres9.2

卸载PostgreSQL9.2.4

brew cleanup postgresql

搞定!

QCon上海2013大会流水账

Monday, November 4, 2013

QCon2013Shanghai

Day 1


上午是来自Twitter,LinkedIn,Github等大公司的四场英文主题演讲,演讲内容也比较泛,英文不好也太听明白,借了个同声传译的耳机,翻译质量也很一般很多术语翻得不准,听得费劲, 后来就听原声了。

  • 第一场是有来自Twitter的Raffi做的《Twitter面向服务的架构之路》, 介绍了Twitter这样一个高速变革高速发展的系统中,维持高并发而采取的一系列解决方案,以及管理系统复杂性所采取的一些设计理念. 其中讲到他们的RPC框架Finagle,有高并发需求的同学可以研究一下, 他们的Timeline cache也是用Redis在做。

  • 第二个主题演讲是来自Linkedin, 数据产品化,作为一个全球最大的职业类SNS,介绍他们如何通过数据进行产品化的思路,并展示了一些相关算法模型。 数据沉淀到一定规模后其实都应该考虑数据产品话,推荐系统是提高转化率的一个好方式。

  • 第三个主题演讲是来自Github的分享: 干掉产品经理, 大多数公司都会设置一个产品主管或者一堆产品经理来决定产品要有哪些功能特性, 但是,有一些企业正在抛开产品经理, 完全让开发者来决定应该实现哪些功能.
    当然Github的团队水平相当高,产品也特殊,这样一个产品工程师每天都要用,所以MicroSoft的“Eat Your Own Dogfood”很重要.

  • 上午最后一个的讲机器的同理心(Mechanical Sympathy),大概是通过赛车行业的例子来讲在软件开发中的一些理念,不明觉厉哪

下午是专题演讲

第一场在《知名网站案例分析》专题会场听的阿里外贸团队在解决跨境网站中遇到的一些SEO及CDN的问题和解决方案,在SEO对性能优化方便他们通过Google Ajax异步兼容的方式来对系统进行优化,在页面中加入一个meta标记<meta name="fragment" content="!">, 爬虫发现页面含有这个标记会把URL变成htt://xxxx?_escaped_fragment_=, 程序根据?_escaped_fragment标记返回给爬虫快照,这个办法会形成两次请求,他们表示对现有的10%的爬虫占比可以接受, 其中提到通过Agent来判断是否为爬虫是不符合Google规范的,存在降权风险等。 对于地区差异大的网站,图片占大部分的下载资源,所以CDN的架构相当关键, 对于全部图片同步产生带宽成本大问题, 他们采用了同步主要图片(商品第一屏图片)的变通的方式提高用户体验。

后来跑去听《团队文化》专题了,这个专题主要是讲工程师文化以及技术管理中的一些探讨。有来自Github,游戏公司、豆瓣以及座谈讨论会。

豆瓣通过code平台的故事来分享了豆瓣的工程师文化,讲到工程师自发的创建code这样一个项目,慢慢的发展起来成为了豆瓣工程师每天依赖的工作平台,里面讲到一个有趣的事情这个项目并没有产品负责人,在一年的时间里没有全职的工程师投入,大多数需求呗提出来后,几天内就会有工程师主动将其实现,如果安排一个全职的负责人来负责这个code项目,负责人可能为了刷存在感,总会开发些不实用的功能,那么这个项目也许发展不下去了,哈哈哈, 干掉产品经理!!! :-P

在座谈会中有一些不错的观点

  • 创始人的文化就是公司的文化
  • 大牛带小牛是最高效的成长方式
  • 小团队更适合杠杆率高的行业

Day 2


上午我主要是在《推荐系统》专题会场听推荐系统相关的分享,迟到了第一场只听了后半部分,第一场是来自百度的,也是这个专题我觉得讲的比较好的。
主要介绍百度在推荐系统上的实践,有相关推荐、个性化推荐、tag浏览等,通过用户建模、item建模、关联、个性化推荐等策略。根据应用需求和数据特点不断调整算法策略。

下午在《移动应用案例分析》专题会场听了豌豆荚在Android方便的技术研究以及搜狐新闻客户端后端架构的演进和Push系统,讲他们随着发展步伐如何做技术选型,技术架构等。 后面也没有特别感兴趣的主题加上又特别困,就回家了

Day 3


上午在《扩展性、可用性和高性能》专题会场听了篱笆网的技术演进、唯品会如何在很短时间内实现支持5倍流量的系统以及新浪微博分享的基于单元化架构的高性能服务实践。

  • 篱笆网主要是分享了他们如何解决数据访问层的性能优化和架构选型,同时也成就了在国内的互联网界Cassandra这样一个NoSQL产品的成功案例
  • 唯品会分享了在他们做大促销前的准备工作, 面对存在大量历史问题系统是如何做到支持5倍
  • 上午的最后一个演讲是来自新浪微博关于单元化架构的实践,通过单元化架构并行计算、数据本地化等方式来提高性能。

下午第一场是一个老外讲企业创新,这哥们后面还做了一个可穿戴计算的生态圈的介绍,中间有演示Google Glass,Facebook前端工程师Hedger Wang介绍碎片化终端整合的思考,下午场最喜欢这个演讲了,介绍了Web App和Native app的一些选择,如何更好的跨终端设计,以及Web App在跨终端的一些解决方案。 其中讲到到底是Web还是Native,Web的优势是广度的,当用户越来越多的时间花在你的app上的时候,我们应该把他带到Native上。 我觉得Web和Native都要有,呵呵,在资源不够的时候应该先Web再Native。 后面有讲到应该用Web Components的方式来解决跨终端web问题,而不是每个终端做一个相同功能的产品,通过Web Components方式来渲染适合各种终端的展现,这个不错有空要研究下。

后面几个是跨界演讲,应该算Lighting Talk 鬼脚七分享了他如何做自媒体,蔡学镛分享了他的成长经历,以及Roy历分享黑客的自我修养,这几个Lighting Talk听起来要轻松些。

总结


本次大会的内容主要集中在大公司的大架构分享, 云计算和高并发等, 缺少Startup相关的分享,三天的大会时间有点长,整个听下来比较累,还是有不少收获的,见到了好多老朋友和认识了一些新朋友,比较喜欢的Topic有:

【转】与成功学大师对话

Friday, March 15, 2013

原文链接: http://book.douban.com/review/2043761/

我已经三十出头了。我虽然赚得了人生的第一桶金,也颇受业内人士的称赞,可胡润那个排行榜上还看不到我的名字。即使比起榜上最后一名,我的资产总额还差人家一个数量级。

我读过《高效能人士的七种习惯》,知道按步就班地接近目标;我也读过《细节决定成败》,懂得谨小慎微地苦心经营;我还读过《第五项修炼》,努力把自己的团队建设成“学习型组织”。可是,我总觉得自己还没有参透生意经,于是四处寻访高人指点。经朋友介绍,我到香港拜会过南怀瑾,也到泰国求教过白龙王。这二位爷给我讲了一番大道理,听后我却觉得不知所云。

土菩萨拜过了,只有求洋神仙。我的师弟小田在美国留学,一次他提到该国的成功学大师科鲁奇。据说此公著作等身,妙语连珠,风靡全美。“通用”以前的老总韦尔奇是他的好友,投资家巴菲特也是他府上的常客。几经反复,小田终于帮我联络上了科鲁奇大师。他答应给我提供一小时咨询,要价一万美金。一万就一万吧,只要能借我一双慧眼。

会面安排在加州某处度假胜地,原来大师在这里置了一套别墅。只见窗外阳光棕榈,沙滩美女,室内则书册满架,茶香扑鼻,另是一番光景。大师须发灰白,却红光满面,精神矍铄。我呈上一万美金的支票,另加一套国产高档瓷器,权作见面礼。大师点头收下,张口就杀我个下马威:“你看上去还很年轻,何必急着发财?”   我心下不快,却不动声色,说了句漂亮话:“弟子知晓富贵如浮云过眼,乃身外之物。只是若不及早成就一番事功,此生虚度就太可惜了。恳请大师不吝赐教。”

“好。”大师颔首微笑,“你们中国历史悠久,中国人也喜欢听故事。我就给你讲四个段子如何?每个段子揭示一件成功法宝。你听后自然有所领悟。”

冰球选手的生日

大师呷了口茶,接着问道:“你有没有看过冰球比赛?”

“没有,只在电视上见过。”

“我小时候在加拿大长大,这项运动在那里很盛行。有一年,我和新婚妻子去看两支劲旅的决赛。因为离比赛开始还有一段时间,我们就拿了份介绍选手背景的资料。我只粗粗扫了几眼,妻子却有所发现——‘你看,绝大部分冰球手出生在冬天!’

“我觉得她大惊小怪,便仔细查看了球手的生日。不错,大部分球手的生日都集中在一至三月,尤其以一月为多。我正感到奇怪,妻子已经根据女人的直觉提出了解释。她说冬天出生的人属于魔羯座或水瓶座,前者踏实稳重,富有毅力;后者灵动活泼,勇于创新。这两种人在冰球这种团队比赛中最容易胜出。他们分别担当后卫和前锋,就能组成一支强大的球队。你觉得这种解释合理吗?”

我简单答道:“弟子不相信星座之说,不过,我也常听人讲起性格如何决定命运。”

大师道:“起初我也觉得冬天出生的人具有某种特殊秉赋。不过,我很快联想起自己早年入学的日期要求。加拿大政府规定,新年那一天满七周岁的孩子才可以入读小学。你如果出生在一月二号,即使离七周岁就差一天,也必须等到来年才能入学,而你的同学则有可能比你小十二个月。你一定猜到了,因为几个月的年龄差距,冬天出生的孩子就比班上大部分同学长得高出一截。”

“不错,可这又说明什么?”

“加拿大的教练一般从十岁左右的孩子中挑选少年选手,再加以培养。那些冬天出生的孩子因为入学晚,比别人高出一截,体格也强壮一些,就容易被选入冰球培训队,尤其是那些最好的球队。他们因而有了一流的教练作指导,也有一流的球员互相切磋。他们十分清楚自己的职业前景,因此付出的努力也是普通少年球手的两三倍。等到十四五岁,这些“冬生冰球手”的水平已经明显超过那些夏秋两季出生的孩子,他们也就有机会晋升到省级和国家级的顶尖球队中。你看,起初一点优势,就会被命运逐渐放大。

“所以,我说的第一件法宝不是性格,而是势差。”

披头士与脱衣舞

大师书房里摆放着一套视听设备,他凝神望着其中一台硕大的音箱,突然问我:“你们这代中国青年大都听过摇滚乐,你是否记得这种流行音乐的始祖?”

“我想是披头士吧,不过我不怎么听他们的歌曲。”

“没错。我年轻的时候,披头士红极一时。我当时在加州作嬉皮,头发留得很长,整天抱着吉它,背着录音机,和朋友们开派对。”说到这里,大师不禁莞尔。“我虽是披头士的粉丝,内心也有几分妒嫉。我自忖音乐细胞不少于约翰-列侬,也曾和其他伙伴共同组建过乐队,可我们吸引的姑娘远远少于披头士招来的女观众。披头士为什么能成名?我找来该乐队成员的传记,谜底终于被我发现了。

“披头士没出道以前,只是一帮爱弄摇滚的英国混混。一天,幸运女神光顾了他们。一个利物浦商人邀请他们去德国汉堡演出——别以为是什么正儿巴经的场合,不过为脱衣舞娘伴奏罢了。有个叫布诺的汉堡人拥有一家脱衣舞酒吧,当时德国还没有摇滚乐队,他去伦敦雇佣演奏者,碰巧遇到那个利物浦商人。事情就这样发生了。披头士在汉堡赚了点小钱,搞了搞女人,大概跟今天北京三里屯酒吧里的乐手也没什么区别。

“大师居然知道三里屯?”

“呵呵,我两年前去北京讲学。一天晚上,美国大使馆一位老朋友在那儿请我喝了点啤酒。接着说披头士。你知道,脱衣舞酒吧里的顾客音乐品位都不高,老板给得报酬也不多。可有一样,这种酒吧在德国的营业时间很长,披头士必须没日没夜地弹唱。日积月累,来美国发展之前,他们已经拥有了七年的演出经验,演奏技巧也达到了相当高超的境界。再加上列侬的创造天份,四人一炮打响也就不难理解了。”

“那您当年为何没有去脱衣酒吧应聘?”话一出口,我即知失言,不由吐了一下舌头。

大师却不介意:“我们嬉皮在性爱方面很开放,但不屑于出入这类声色场所。我和伙伴们试过几家唱片公司,全都碰了钉子,败兴而归。如果当年能拥有一个小小的演出场所,或许我也能在娱乐界扬名立万呢。

“所以,我说得第二件法宝不是技巧,而是舞台。”

盖茨生逢其时

讲到这里,大师悠悠叹了口气:“我最大的遗憾还不是没有成为摇滚乐明星,而是错过了当比尔-盖茨这类人物的机会。”

我一惊,差点把手中的茶碗掉到地上。

“盖茨的故事不用我重复了。不过,你有没有注意过他是哪年出生的?”

“如果弟子没有记错,应该是1955年10月28日。”盖茨的传记我买了不只一本,曾经反复研读。

“不错,他和我一样,是金秋十月出生的。不过不像冰球手,这其中倒没有奥秘。”大师谈兴正浓,接着讲道:“你若是读过点技术史,就知道1975年1月是硅谷最重要的时刻。正是那时,8800型个人电脑诞生了,成为当月《大众电子》杂志(Popular Electronics)的封面故事。不少人都看出电脑市场蕴含的巨大商机,可谁会先下海呢?如果你年纪够大,很可能已经在IBM之类的老牌公司谋到职位,再去自己创业机会成本太大;如果你年纪太小,恐怕还没有掌握必要的IT技能。因此,你的年纪必须恰到好处,才能显出英雄本色。盖茨当时正好从哈佛肄业,不过二十出头。他既懂编写软件,又是初生牛犊,于是抓住了黄金商机。

“同样靠微软挤进福布斯排行榜的富人们,只比盖茨大一点或小一点。保罗-艾伦生于1953年,他在高中电脑房里就认识盖茨;斯蒂夫-鲍尔默生于1956年,得以在哈佛结识盖茨。我再举两个例子:苹果电脑的创始人乔布斯生于1955年,谷歌现任CEO施密特也生于这一幸运年份。

“请问大师的生辰?”我不禁好奇。

“哈哈,我生于1950年,不过我也不是没有机会参加IT界革命。我过了几年流浪的嬉皮生活,于1972年申请就读瑞德大学(Reed College)的电子工程专业。那一年乔布斯也搬了进来,我们在校园里还打过几次照面。可他比我有决断,一年后就辍学了,后来跑到硅谷闯出了一片天地。本科毕业后,我又鬼使神差地对社会学发生了兴趣,在东岸一所常青藤大学读了个博士。如此一来,个人电脑时代的所有商机都被我错过了。”

“这么说,盖茨并非绝顶聪明?”

“盖茨当然是个聪明人,不过他的智慧也并非高得不可想像。我成名之后,他找我做过一两次咨询。那时他已然是世界首富,在事业方面我就没有再提建议。我和他聊起美国企业家的发家史,他反应很快,我提个大概,他就猜出每位富豪的经营诀窍。可他的机敏程度比我的好友德鲁克还是慢了半拍。

“所以,我说得第三件法宝不是智商,而是时运。”

塞翁失马的弗洛姆

讲到这里,一个小时就快到了。大师抬头看了看墙上的挂钟,告诉我不要着急:“我会把第四个段子讲完,否则你要跟我打官司了。这最后一个故事嘛,也和律师有关系。

“我从东部那所大学毕业后,想先到社会上打拼一番,就去曼哈顿上城一家律师事务所作了实习生。那家律所的合伙人中,有一位身材五短,背还有点驼,名叫弗洛姆。你别看他其貌不扬,以前还是哈佛法学院的高材生呢。不过,弗洛姆五十年代毕业后,因为他的犹太背景和主流社会不太搭调,有段时间找不到工作。最后,他加入了一家新成立的律所。这家公司是如此不起眼,以致于什么上门的活儿都接。可是,它成长迅速,如今已经拥有两千名律师,年收入高达十亿美元。

“我作实习生的时候,有一次吃饭碰到老板弗洛姆,就向他请教发家秘诀。他告诉我你们中国一句古话——塞翁失马,焉知非福。五十年代的华尔街还有点贵族风度,有点名气的律所都不愿意接“敌意收购”(hostile takeover)这类脏活。如果实在不好退却,他们就把脏活转包给弗洛姆的公司。转眼到了七十年代,金融管制放松了,信贷资金充裕了,投资者也变得气势汹汹了。这一切都推动了企业收购大潮。现在所有的律所都愿意接并购案了,不过你可以想到,只有弗洛姆的公司做得最为出色——因为他们已经积累了近二十年的从业经验。

“我在八十年代初见到弗洛姆时,他的生意如此火爆,连我这种非科班出身的学生都被招了进来。那餐饭快吃完的时候,他对我讲‘行行出状元。你一旦干这行有了名声,人们就会首先想到你。’”

我问道:“那么,大师为什么后来又离开了那家律所?”

“通过弗洛姆,我终于明白,我再也不能跟在别人后面打工了。我必须做点别人没有做过的事情,于是决定钻研杰出人物成功的秘密。三十年后,你不是也找到我了吗?现在,轮到你这个中国人尝试些新领域了。

“所以,我说得第四种要素不是能力,而是先机。”

大师讲完这四个段子,起身走向窗前,若有所思地吟出一句唐诗:“只在此山中,云深不知处。”他转过头对我说:“我年轻时一直以为,那些大人物是靠他们的真才实学成功的;现在才明白,真才实学也要靠外在的机缘才能造就。你总以为自己修炼不够,其实还未将大局看透。”

我就此拜别了科鲁奇大师。出门后,师弟小田问我,这一万美金花得值不值。我平日里精打细算,这时却冒出一句偈语:“运用之妙,存乎一心”。

[后记] 《非同凡响》(outliers,中文版译为“异类”,殊觉不妥)是去年年底在美国出版的一部非虚构类畅销书。据说此书的中译本在台湾出版后并未大卖,我的一位编辑朋友猜想,可能是此类图书不适合华人读者口味的缘故。我于是想到通过一位虚拟的成功学大师,来讲述书中的四个成才故事。有些读者也许已经发现,我参考的文本主要有两个:古龙的《七种武器》和金庸的《雪山飞狐》。

此文已刊于《优势》杂志创刊号。
作者博客:blog.sina.com.cn/tianfm

用Buildout来构建Python项目

Tuesday, March 12, 2013

什么是Buildout

alt Buildout
(Remixed by Matt Hamilton, original from http://xkcd.com/303)

Buildout是一个基于Python的构建工具, 通过一个配置文件,可以从多个部分创建、组装并部署你的应用,即使应用包含了非Python的组件,Buildout也能够胜任. Buildout不但能够像setuptools一样自动更新或下载安装依赖包,而且还能够像virtualenv一样,构建一个封闭隔离的开发环境.

初始化Buildout

首先我们新建一个目录来共享Buildout配置和文件:

~/Projects$ mkdir buildout
~/Projects$ cd buildout

下载一个2.0的bootstrap.py脚本:

~/Projects/buildout$ wget http://downloads.buildout.org/2/bootstrap.py

然后创建一个Buildout的配置文件:

~/Projects/buildout$ touch buildout.cfg

运行bootstrap.py来生成Buildout相关的文件和目录:

~/Projects/buildout$ python bootstrap.py
Creating directory '/Users/Eric/Projects/buildout/bin'.
Creating directory '/Users/Eric/Projects/buildout/parts'.
Creating directory '/Users/Eric/Projects/buildout/eggs'.
Creating directory '/Users/Eric/Projects/buildout/develop-eggs'.
Generated script '/Users/Eric/Projects/buildout/bin/buildout'.

从上面可以看出,创建了目录bin,parts,eggs,develop-eggs,在bin目录下生成了buildout脚本:

  • bin目录用来存放生成的脚本文件
  • parts目录存放生成的数据,大多用不上
  • develop-eggs 存放指向开发目录的链接文件。和buildout.cfg中develop选项相关
  • eggs 是存放从网络上下载下来的egg包。这些包一般在buildout.cfg中的egg选项里定义

把Python和Pyramid集成进来

配置Buildout

~/Projects/buildout$ vim buildout.cfg
[buildout]
# 每个buildout都要有一个parts列表,也可以为空。
# parts用来指定构建什么。如果parts中指定的段中还有parts的话,会递归构建。
parts = tools

[tools]
# 每一段都要指定一个recipe, recipe包含python的代码,用来安装这一段,
# zc.recipe.egg就是把一些把下面的egg安装到eggs目录中
recipe = zc.recipe.egg
# 定义python解释器
interpreter = python
# 需要安装的egg
eggs =
    pyramid

执行buildout命令来构建一下, 这将会把Pyramid集成进来:

~/Projects/buildout$ bin/buildout

用buildout来构建项目

现在可以创建Pyramid应用了:

~/Projects/buildout$ bin/pcreate -t starter myproject

配置一下Buildout:

~/Projects/buildout$ vim buildout.cfg
[buildout]
parts =
    tools
    apps
develop = myproject

[tools]
recipe = zc.recipe.egg
interpreter = python
eggs =
    pyramid

[apps]
recipe = zc.recipe.egg
eggs = myproject

再次运行一下buildout:

~/Projects/buildout$ bin/buildout

现在可以再buildout的环境中启动myproject了:

~/Projects/buildout$ bin/pserve myproject/development.ini
Starting server in PID 40619.
serving on http://0.0.0.0:6543

最佳实践/Tips

1. 固化egg的版本

把所有的版本信息写到[versions]里面:

extends = versions.cfg
versions = versions
show-picked-versions = true

配置中的“show-picked-versions = true “会在运行buildout的时候把所有的版本打印出来, 把它写到"versions.cfg"中就可以固化了:

[versions]
Chameleon = 2.11
Mako = 0.7.3
MarkupSafe = 0.15
PasteDeploy = 1.5.0
WebOb = 1.2.3
distribute = 0.6.35
repoze.lru = 0.6
translationstring = 1.1
venusian = 1.0a7
zc.buildout = 2.0.1
zc.recipe.egg = 2.0.0a3
zope.deprecation = 4.0.2
zope.interface = 4.0.5

# Required by:
# pyramid-debugtoolbar==1.0.4
Pygments = 1.6

# Required by:
# myproject==0.0
pyramid = 1.4

# Required by:
# myproject==0.0
pyramid-debugtoolbar = 1.0.4

# Required by:
# myproject==0.0
waitress = 0.8.2

2. 使用mr.developer插件来组织大型的项目, 让开发更方便

[buildout]
...
extensions = mr.developer

3. 开发环境 VS 生产环境

我们可以创建多个配置文件, 比如把buildout.cfg作为生产环境的配置, 把develop的配置从buildout.cfg删除, 创建一个development.cfg作为开发环境的配置:

[buildout]
extends = buildout.cfg
develop = myproject

升级Buildout到2.0版本

Tuesday, March 12, 2013

Buildout已经升级到2.0了, 刚刚升级了一下, 发现一些地方要注意.

  • 我们先要替换掉原来的bootstrap.py脚本, 下载新的2.0的bootstrap: http://downloads.buildout.org/2/bootstrap.py.

  • 新版本的buildout不再支持“buildout-versions” 和 “buildout.dumppickedversions“, 这个插件的功能已经内置了, 把show-picked-versions = true加到配置文件里面就行了.

    [buildout]
    ...
    show-picked-versions = true
    ...
    

推荐一个Python的异步的BDD框架-pyVows

Friday, November 9, 2012

pyVows, 这一个异步的BDD测试框架

想象我们正在测试一个加法函数:

def test_sum_returns_42():
    result = add_two_numbers(41, 1)

    assert result
    assert int(result)
    assert result == 42

尽管在这样一个非常简单的场景中, 我们有三个断言在这个测试中, 这样不太好, 我们想要每个测试一个断言, 所以我们可以这样:

def test_sum_returns_result():
    result = add_two_numbers(41, 1)
    assert result

def test_sum_returns_a_number():
    result = add_two_numbers(41, 1)
    assert int(result)

def test_sum_returns_42():
    result = add_two_numbers(41, 1)
    assert result == 42

除了add_two_numbers 这个函数被执行了三次, 一切OK. 当然在这么简单的测试中, 一个函数被执行多次也没关系, 但在真实的项目中, 我们应该减少调用次数, 这样我们的测试才能跑的更快。

我们可以用pyVows做如下的改进:

class SumContext(Vows.Context):

    def topic(self):
        return add_two_numbers(41, 1)

    def we_get_a_result(self, topic):
        expect(topic).Not.to_be_null()

    def we_get_a_number(self, topic):
        expect(topic).to_be_numeric()

    def we_get_42(self, topic):
        expect(topic).to_equal(42)

如果没看懂没关系, 我们再来看看下面这个例子

我们来做除零测试:

# division_by_zero_vows.py

from pyvows import Vows, expect

# Create a Test Batch
@Vows.batch
class Divisions(Vows.Context):
    class WhenDividingANumberByZero(Vows.Context):
        def topic(self):
            return 42 / 0

        def we_get_division_by_zero_error(self, topic):
            expect(topic).to_be_an_error_like(ZeroDivisionError)

    class WhenDividingByOne(Vows.Context):
        def topic(self):
            return 42 / 1

        def we_get_the_same_number(self, topic):
            expect(topic).to_equal(42)

我们来执行一下:

 $ pyvows division_by_zero_vows.py

 ============
 Vows Results
 ============

   OK » 2 honored  0 broken (0.000756s)

现在我们来看一个更为复杂一点的例子, 假设我们有一个水果对象模块叫the_good_things:

class Strawberry(object):
    def __init__(self):
        self.color = '#ff0000';

    def isTasty(self):
        return True

class PeeledBanana(object): pass

class Banana(object):
    def __init__(self):
        self.color = '#fff333';

    def peel(self):
        return PeeledBanana()

现在我们来写一些测试在 the_good_things_vows.py:

from pyvows import Vows, expect
from the_good_things import Strawberry, Banana, PeeledBanana

@Vows.batch
class TheGoodThings(Vows.Context):
    class AStrawberry(Vows.Context):
        def topic(self):
            return Strawberry()

        def is_red(self, topic):
            expect(topic.color).to_equal('#ff0000')

        def and_tasty(self, topic):
            expect(topic.isTasty()).to_be_true()

    class ABanana(Vows.Context):
        def topic(self):
            return Banana()

        class WhenPeeled(Vows.Context):
            def top