飞龙札记https://feilong.me/2023-06-05T11:20:00+08:00自律2023-06-05T11:20:00+08:002023-06-05T11:20:00+08:00飞龙tag:feilong.me,2023-06-05:/2023/06/self-discipline.html<p>家里的追星(张信哲)近30年了吧,认识这么多年来,第一次请她看张信哲的演唱会(有点说不过去),看完非常震撼,看下图的现场盛况,座无虚席,张信哲也成功斩获一枚新小迷弟:)
<img alt="jeff1" src="/static/2023/06-05-jeff2.jpeg"></p>
<p>有时候在网易云也会翻看一些很好听的歌的现场版视频,现场唱的和录的歌或MV差别还是挺大,甚至有不少现场翻车的,其中也不乏一些大牌的明星的歌,但现场听张信哲跟听磁带、听网易云音乐的感觉几乎一模一样(又绝不是假唱),这嗓子、这音色能保持几十年如一日,没有超强的自律是不可能做到的:</p>
<ul>
<li>抽烟</li>
<li>喝酒</li>
<li>好吃爽口但刺激性强的食物</li>
<li>熬夜</li>
<li>浪玩</li>
<li>……</li>
</ul>
<p>要一次抵住这些诱惑容易,要长时间抵住这些诱惑太难太难,比如我不抽烟喝酒,但是不让我吃辣椒、海鲜等,那哪有生活滋味。</p>
<p>从远景拍到的照片来看,他这个年纪,身材也保持的很好(对比我已隆起的小肚腩),这也需要克制饮食和坚持锻炼,不信看看大小罗。
<img alt="jeff1" src="/static/2023/06-05-jeff1.jpeg"></p>
<p>要保持演唱的状态,还得勤于排练,虽然这些歌他闭着眼睛也能唱,但要在现场每次都不出一点差错,不跑调、不错词、节奏不错乱,也不容易。还要灵活机变的响应现场的粉丝互动,包括各大城市收尾阶段报读绝不一样的一大段要死记硬背的赞助商名单,这都是要做充分的准备的。</p>
<p>还有一点,虽然他的歌不少 …</p><p>家里的追星(张信哲)近30年了吧,认识这么多年来,第一次请她看张信哲的演唱会(有点说不过去),看完非常震撼,看下图的现场盛况,座无虚席,张信哲也成功斩获一枚新小迷弟:)
<img alt="jeff1" src="/static/2023/06-05-jeff2.jpeg"></p>
<p>有时候在网易云也会翻看一些很好听的歌的现场版视频,现场唱的和录的歌或MV差别还是挺大,甚至有不少现场翻车的,其中也不乏一些大牌的明星的歌,但现场听张信哲跟听磁带、听网易云音乐的感觉几乎一模一样(又绝不是假唱),这嗓子、这音色能保持几十年如一日,没有超强的自律是不可能做到的:</p>
<ul>
<li>抽烟</li>
<li>喝酒</li>
<li>好吃爽口但刺激性强的食物</li>
<li>熬夜</li>
<li>浪玩</li>
<li>……</li>
</ul>
<p>要一次抵住这些诱惑容易,要长时间抵住这些诱惑太难太难,比如我不抽烟喝酒,但是不让我吃辣椒、海鲜等,那哪有生活滋味。</p>
<p>从远景拍到的照片来看,他这个年纪,身材也保持的很好(对比我已隆起的小肚腩),这也需要克制饮食和坚持锻炼,不信看看大小罗。
<img alt="jeff1" src="/static/2023/06-05-jeff1.jpeg"></p>
<p>要保持演唱的状态,还得勤于排练,虽然这些歌他闭着眼睛也能唱,但要在现场每次都不出一点差错,不跑调、不错词、节奏不错乱,也不容易。还要灵活机变的响应现场的粉丝互动,包括各大城市收尾阶段报读绝不一样的一大段要死记硬背的赞助商名单,这都是要做充分的准备的。</p>
<p>还有一点,虽然他的歌不少,但最流行还是那些,这么多年翻来翻去唱这些歌,没有对歌唱事业的热爱或者自律也是较难坚持的,比如对于我来说重复做一样的事情就非常难,我特别讨厌做重复的事情,以我目前的修为,如果是我我早唱吐了,能挣再多的钱和掌声我也唱不下去。</p>
<p>再从下图看他演唱会的排期密度,两天连轴唱,五天之内要紧锣密鼓的转战到另一个城市继续连轴转,这么成功的张信哲还这么拼,真的是很汗颜,对比之下我还有什么理由不努力、还有什么要抱怨的呢?</p>
<p><img alt="jeff1" src="/static/2023/06-05-jeff3.jpeg"></p>
<p>刚入华为时曾学到过一句很经典的话“一辈子假积极,就是真积极”,不管张信哲对唱歌是真热爱还是假积极几十年,我敢说他这就是真自律、真积极。</p>
<p>PS:赶时髦尝试用ChatGPT“以张信哲唱歌自律为题材写一篇作文”,结果如下,当对比:</p>
<blockquote>
<p>题目:张信哲唱歌自律的力量 </p>
<p>作文: </p>
<p>自律是成功之路上不可或缺的品质,它可以引领一个人走向更高的成就。而当谈及唱歌自律的话题时,我们不得不提到华语乐坛的一位传奇歌手——张信哲。他的音乐才华和自律精神为无数人树立了榜样,激励着我们追求卓越。 </p>
<ul>
<li>首先,张信哲通过对自己的严格要求展现了唱歌自律的力量。作为一名出色的歌手,他在音乐上不断追求完美。无论是音准、音色还是咬字,他都力求做到最好。为了保持良好的状态,他不断练习唱歌技巧,并积极参与音乐培训。他深知自律是提升实力的关键,因此他时刻保持着对自己高标准的要求,从而塑造出深情厚意的歌声,感染了无数人的心灵。 </li>
<li>其次,张信哲的自律精神也体现在他对职业的敬业态度上。作为一名优秀的艺人,他深知自己承载着观众的期待和信任。无论是在演唱会还是在录音室里,他都会全身心地投入到音乐中。他严格遵守排练时间,精心准备每一场演出,并积极与团队合作,力求将最好的表现带给观众。他对音乐事业的热爱和专注让他在乐坛站稳脚跟,并不断获得认可和赞赏。 </li>
<li>此外,张信哲还通过自律实现了自我突破和成长。他不满足于舒适区的成绩,而是勇敢地尝试不同的音乐风格和创作风格。他不断探索和学习,提升自己的音乐造诣。他对自己的要求从未停止,通过自我超越不断刷新着自己的极限。正是因为他的自律,他能够跨越自我,不断成长,成为乐坛的一颗璀璨明星。 </li>
</ul>
<p>总结起来,张信哲唱歌自律的故事给我们带来了巨大的启示。他通过对自己的严格要求、对职业的敬业态度和不断的</p>
</blockquote>我跟他很熟2022-06-09T11:20:00+08:002022-06-09T11:20:00+08:00飞龙tag:feilong.me,2022-06-09:/2022/06/he-is-my-close-friend.html<blockquote>
<p>鸿渐说:“philophilosophers 这个字很妙,是不是先生用自己头脑想出来的?”<br>
“这个字是有人在什么书上看见了告诉 Bertie,Bertie 告诉我的。”<br>
“谁是 Bertie?”<br>
“就是罗素了。”<br>
世界有名的哲学家,新袭勋爵,而褚慎明跟他亲狎得叫他乳名,连董斜川都羡服了,便说:“你跟罗素很熟?”<br>
“还够得上朋友,承他瞧得起,请我帮他解答许多问题。”天知道褚慎明并没吹牛,罗素确问过他什么时候到英国、有什么计划、茶里要搁几块糖这一类非他自己不能解答的问题”</p>
</blockquote>
<p>《围城》文中随处可见各种尖酸的比喻与讽刺,以往总觉得言过其实,似有些夸张。当再次读到上面这一段时,仿佛自己不可告人的隐私突然被人在公开场合揭发了一样,脊梁骨直冒凉气,有想找个地缝钻的无地自容之感。这哪里夸张,这不写的也是我么?</p>
<ul>
<li>我是不是常挂“我跟他很熟”于嘴边?</li>
<li>我是不是常在人前直呼他人的名字以显得我跟这人很熟?</li>
<li>我是不是常吹我有个朋友怎么怎么牛逼?好像牛逼的那人其实是我而不是他一样!</li>
<li>我是不是常胸脯拍的山响,说我帮你介绍XXX、我帮你问问XXX、我找XXX帮你解决下?实际上拍完胸脯就不了了之!</li>
<li>我是不是常在帮过人之后,恨不得天下人都知道,没事就有意无意的向人提及?</li>
<li>我是不是常在别人读某书时显摆自己读过且很熟悉很懂里面的内容的样子?甚至有一些妒意 …</li></ul><blockquote>
<p>鸿渐说:“philophilosophers 这个字很妙,是不是先生用自己头脑想出来的?”<br>
“这个字是有人在什么书上看见了告诉 Bertie,Bertie 告诉我的。”<br>
“谁是 Bertie?”<br>
“就是罗素了。”<br>
世界有名的哲学家,新袭勋爵,而褚慎明跟他亲狎得叫他乳名,连董斜川都羡服了,便说:“你跟罗素很熟?”<br>
“还够得上朋友,承他瞧得起,请我帮他解答许多问题。”天知道褚慎明并没吹牛,罗素确问过他什么时候到英国、有什么计划、茶里要搁几块糖这一类非他自己不能解答的问题”</p>
</blockquote>
<p>《围城》文中随处可见各种尖酸的比喻与讽刺,以往总觉得言过其实,似有些夸张。当再次读到上面这一段时,仿佛自己不可告人的隐私突然被人在公开场合揭发了一样,脊梁骨直冒凉气,有想找个地缝钻的无地自容之感。这哪里夸张,这不写的也是我么?</p>
<ul>
<li>我是不是常挂“我跟他很熟”于嘴边?</li>
<li>我是不是常在人前直呼他人的名字以显得我跟这人很熟?</li>
<li>我是不是常吹我有个朋友怎么怎么牛逼?好像牛逼的那人其实是我而不是他一样!</li>
<li>我是不是常胸脯拍的山响,说我帮你介绍XXX、我帮你问问XXX、我找XXX帮你解决下?实际上拍完胸脯就不了了之!</li>
<li>我是不是常在帮过人之后,恨不得天下人都知道,没事就有意无意的向人提及?</li>
<li>我是不是常在别人读某书时显摆自己读过且很熟悉很懂里面的内容的样子?甚至有一些妒意,好像就我懂,你不懂!</li>
<li>我是不是……</li>
</ul>
<p>也不是说我完全没有意识到这些问题的存在,偶尔心中也会有一丝悔意觉得不应如此,但不知不觉“我跟他很熟”就会脱口而出。说到底,还是个人修为不到位,没有深刻的意识到如果这些点再放大一些,我就是另一个令人作呕的褚慎明,慎之慎之!</p>历史的车轮滚滚2021-12-30T09:20:00+08:002021-12-30T09:20:00+08:00飞龙tag:feilong.me,2021-12-30:/2021/12/wheel-of-history.html<p>重读《万历十五年》有一种沉重的无力感,不管是张居正、申时行、海瑞还是万历皇帝,张居正亲撰教材苦心孤诣教育皇帝,破除一切阻力力行改革;申时行极力调和阴阳缓和矛盾和稀泥,算是玩的一手好太极,可余生的23年却不得不远离庙堂孤老家乡;海瑞以儒家传统为圭臬,严于律己、苛于他人与流于现实的世俗官场人物格格不入,象一把悬于高堂的宝剑,枉有天下第一疏而不为所用;万历皇帝也曾循规蹈矩安于教诲,踌躇满志想效仿列祖列宗成就一番伟业,然终归于匪夷所思的不理不睬、不管、不作为而又不放的“无为”状态;他们都无法改变滚滚向前而行将崩溃的大明王朝。</p>
<p>这种无力感特别可怕,可怕的是不管你道德高尚或卑劣、有能或无能、有权或无权、作为或不作为,都好比尘路上的一粒沙被滚滚车轮无情的碾过,对车轮转速和方向的影响似有似无,沙砾大点如张居正或许引起了一点点小颠簸后,可似乎很快又恢复如初。你也不知道从何时何地算起,车轮就已经偏离了、失速了,最终毫无悬念的坠入了深渊。我们后人来回溯历史车轮的全程,想要找到这个时这个地也几无可能,或祸端本就肇始于洪武,或永乐砍瓜切菜祸祸了一波,或嘉靖神仙般勉强还维系了一把,或锅也不应该盖在万历身上,上至皇帝文武百官,下至黎庶万民,到底是谁的锅可能都说不上,但作为历史的参与者又都有份。大风起于青萍之末,末在哪无从得知也无需深究,这或许就是历史发展的必然 …</p><p>重读《万历十五年》有一种沉重的无力感,不管是张居正、申时行、海瑞还是万历皇帝,张居正亲撰教材苦心孤诣教育皇帝,破除一切阻力力行改革;申时行极力调和阴阳缓和矛盾和稀泥,算是玩的一手好太极,可余生的23年却不得不远离庙堂孤老家乡;海瑞以儒家传统为圭臬,严于律己、苛于他人与流于现实的世俗官场人物格格不入,象一把悬于高堂的宝剑,枉有天下第一疏而不为所用;万历皇帝也曾循规蹈矩安于教诲,踌躇满志想效仿列祖列宗成就一番伟业,然终归于匪夷所思的不理不睬、不管、不作为而又不放的“无为”状态;他们都无法改变滚滚向前而行将崩溃的大明王朝。</p>
<p>这种无力感特别可怕,可怕的是不管你道德高尚或卑劣、有能或无能、有权或无权、作为或不作为,都好比尘路上的一粒沙被滚滚车轮无情的碾过,对车轮转速和方向的影响似有似无,沙砾大点如张居正或许引起了一点点小颠簸后,可似乎很快又恢复如初。你也不知道从何时何地算起,车轮就已经偏离了、失速了,最终毫无悬念的坠入了深渊。我们后人来回溯历史车轮的全程,想要找到这个时这个地也几无可能,或祸端本就肇始于洪武,或永乐砍瓜切菜祸祸了一波,或嘉靖神仙般勉强还维系了一把,或锅也不应该盖在万历身上,上至皇帝文武百官,下至黎庶万民,到底是谁的锅可能都说不上,但作为历史的参与者又都有份。大风起于青萍之末,末在哪无从得知也无需深究,这或许就是历史发展的必然,事物发展的必然,落在一个行业、一家企业,潮起潮落这种无力感又何尝不在呢!</p>无友不如己者2021-03-31T18:20:00+08:002021-03-31T18:20:00+08:00飞龙tag:feilong.me,2021-03-31:/2021/03/not-better-than-your-friends.html<blockquote>
<p>《论语·学而第一》:子曰:“君子不重则不威,学则不固。主忠信。无友不如己者。过则勿惮改。” 《论语·子罕第九》:子曰:“主忠信。无友不如己者。过则勿惮改。”</p>
</blockquote>
<p>对“无友不如己者”这句历来有多种解释,首先两个关键字:</p>
<ul>
<li>无:无可以通“勿”,也可以取无的本意</li>
<li>如:不如除一般的理解外,也见有解释为不像,即跟自己不同,所谓道不同不相为谋</li>
</ul>
<p>这样这句话就有如下几种常见解读:</p>
<ol>
<li>不要跟自己(志向)不同的人交往</li>
<li>不要跟不如自己的人交往</li>
<li>朋友圈没有跟自己(志向)不同的朋友</li>
<li>朋友圈没有不如自己的朋友</li>
<li>没有哪个朋友是不如我自己的</li>
</ol>
<p>3是1的行为结果,4是2的行为结果,故1&3或2&4可以认为意思是相近的两组。</p>
<p>日常中将这句话解析成2&4的最为常见,在我看来也是最常见的一种错误认知,我更倾向于第5中解析,即:“没有哪个朋友是不如我自己的”
,这才能和孔子的另一句名言:“三人行必有我师 …</p><blockquote>
<p>《论语·学而第一》:子曰:“君子不重则不威,学则不固。主忠信。无友不如己者。过则勿惮改。” 《论语·子罕第九》:子曰:“主忠信。无友不如己者。过则勿惮改。”</p>
</blockquote>
<p>对“无友不如己者”这句历来有多种解释,首先两个关键字:</p>
<ul>
<li>无:无可以通“勿”,也可以取无的本意</li>
<li>如:不如除一般的理解外,也见有解释为不像,即跟自己不同,所谓道不同不相为谋</li>
</ul>
<p>这样这句话就有如下几种常见解读:</p>
<ol>
<li>不要跟自己(志向)不同的人交往</li>
<li>不要跟不如自己的人交往</li>
<li>朋友圈没有跟自己(志向)不同的朋友</li>
<li>朋友圈没有不如自己的朋友</li>
<li>没有哪个朋友是不如我自己的</li>
</ol>
<p>3是1的行为结果,4是2的行为结果,故1&3或2&4可以认为意思是相近的两组。</p>
<p>日常中将这句话解析成2&4的最为常见,在我看来也是最常见的一种错误认知,我更倾向于第5中解析,即:“没有哪个朋友是不如我自己的”
,这才能和孔子的另一句名言:“三人行必有我师”相对应,我们要虚心的看到每个人的长处,每个人都有我不如而值得学习的地方,这才是一种积极的、开放的心态,才是待人处友的正确方式。</p>
<p>南怀瑾在《论语别裁》也倾向于这种解释:<br>
<img alt="friends" src="/static/2021/03-31-friends.jpg"></p>求同存异2021-03-30T16:30:00+08:002021-03-30T16:30:00+08:00飞龙tag:feilong.me,2021-03-30:/2021/03/keep-differences.html<p>今天一老同事的微信群里又日常的出现了关于中美问题的撕逼大战,高XX怼天怼地连怼了几个人,最后导致了王XX退群群才归于暂时的安宁。</p>
<p>这个群有300来人,这么多人对一个问题有不同的观点很正常,但是观点不同不至于互怼到似有深仇大恨这种地步,而且逢人便喷,不容有一点不同意见。本群本是一个有共同工作经历的离职同事群,同事之间多少应有一些情面在,如此不顾同事之情,不留余地,真把一个公共群玩成了自留地。</p>
<p>对于高XX发表的言论我持保留意见不予置评,但非常不耻他这种行为。</p>
<p>今日和昨日的自己对同一件事的看法都可能会发生改变而不同,两个人对事很难有一致的意见,这个时候做人应该有开放的心态,求同存异,只有在尊重别人不同意见的前提下铺展开自己的观点,那才是雄辩,不然与大搞人身攻击有什么区别?与村妇掐架有何区别?与狂犬吠日有何区别?</p><p>今天一老同事的微信群里又日常的出现了关于中美问题的撕逼大战,高XX怼天怼地连怼了几个人,最后导致了王XX退群群才归于暂时的安宁。</p>
<p>这个群有300来人,这么多人对一个问题有不同的观点很正常,但是观点不同不至于互怼到似有深仇大恨这种地步,而且逢人便喷,不容有一点不同意见。本群本是一个有共同工作经历的离职同事群,同事之间多少应有一些情面在,如此不顾同事之情,不留余地,真把一个公共群玩成了自留地。</p>
<p>对于高XX发表的言论我持保留意见不予置评,但非常不耻他这种行为。</p>
<p>今日和昨日的自己对同一件事的看法都可能会发生改变而不同,两个人对事很难有一致的意见,这个时候做人应该有开放的心态,求同存异,只有在尊重别人不同意见的前提下铺展开自己的观点,那才是雄辩,不然与大搞人身攻击有什么区别?与村妇掐架有何区别?与狂犬吠日有何区别?</p>谋定而后动2021-03-24T12:00:00+08:002021-03-24T12:00:00+08:00飞龙tag:feilong.me,2021-03-24:/2021/03/think-then-do.html<p>孙子曰:“夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也。多算胜,少算不胜。”</p>
<p>在做一事之前,谋算在前,执行在后。如最近朋友在做的一件产品上,目前的状态我以为谋的还不太够,产品的定位、形态、功能思考的不是很清楚的情况下,却已经在马不停蹄的前行,大事未考虑清楚的情况下,钻进小事情上去很容易跳不出不来,因为在小事情上一是会耗费大量的精力,减少了对大问题的思考;二是小事很容易看到成果和进展,小成功的喜悦会掩盖掉深层次的问题。</p>
<p>我过往的项目经验也有深刻的教训,开发掌游圈的时候,亲自去开发2.0版本的功能代码,纠结于产品的每一个设计小细节,这过程中产生了许多问题,如:导致了后端开发人员的项目参与感很低;对掌游圈和整个公司的未来思考不够。现在回过头来看,产品都已经关闭了,当时写的代码、纠结的功能设计、UI是否对齐等等问题,全部都不重要,最重要的问题倒是当时应该怎么样才能使团队能够积极和谐的为公司发展做贡献,怎么样才可以让公司活下来。</p>
<p>只有谋定而后动才有最大的可能性把事情做成。</p><p>孙子曰:“夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也。多算胜,少算不胜。”</p>
<p>在做一事之前,谋算在前,执行在后。如最近朋友在做的一件产品上,目前的状态我以为谋的还不太够,产品的定位、形态、功能思考的不是很清楚的情况下,却已经在马不停蹄的前行,大事未考虑清楚的情况下,钻进小事情上去很容易跳不出不来,因为在小事情上一是会耗费大量的精力,减少了对大问题的思考;二是小事很容易看到成果和进展,小成功的喜悦会掩盖掉深层次的问题。</p>
<p>我过往的项目经验也有深刻的教训,开发掌游圈的时候,亲自去开发2.0版本的功能代码,纠结于产品的每一个设计小细节,这过程中产生了许多问题,如:导致了后端开发人员的项目参与感很低;对掌游圈和整个公司的未来思考不够。现在回过头来看,产品都已经关闭了,当时写的代码、纠结的功能设计、UI是否对齐等等问题,全部都不重要,最重要的问题倒是当时应该怎么样才能使团队能够积极和谐的为公司发展做贡献,怎么样才可以让公司活下来。</p>
<p>只有谋定而后动才有最大的可能性把事情做成。</p>读通鉴宜记录心得2021-03-16T12:00:00+08:002021-03-16T12:00:00+08:00飞龙tag:feilong.me,2021-03-16:/2021/03/read-zztj.html<p>《资治通鉴》已断断续续读了227卷,虽似懂非懂,读时多少亦有所想,很遗憾的是一直想记录但没有记录下只言片语,如:</p>
<ul>
<li>再读曹参时,才发现曹参深通黄老之术,有自知之明且不伐其功,是真正的大赢家,从韩信功高而不见盖主、随萧何无为而天下大治。</li>
<li>贾谊思想是如此的超前,感觉其思虑过重、见人之所未见是以以忧郁而死,而不是死在伤梁怀王之死。</li>
<li>东晋朝廷腐烂,江陵在南北朝时期的独特地位,王敦、桓温、桓玄等谋位未尝不可,成则刘裕、败则王敦、几成则桓玄。</li>
<li>魏孝文帝拓跋宏迁都、汉化的巨大魄力,是多大的勇气才能做到?</li>
<li>高欢、宇文泰的相爱相杀</li>
<li>唐高祖的历史功绩,没有李渊真能有唐?李渊在家族中的影响力,李渊的韬光养晦,忍一时之辱,李氏宗族子弟在开唐中的功绩。军攻虽李二居半,有李渊没有李二也有李三,没李渊真不一定有唐。</li>
<li>唐太宗纳谏之难</li>
<li>李辅国、鱼朝恩、程元振,为什么除了一个又生另一个甚至过犹不及,藩镇割据亦是?</li>
</ul>
<p>王夫之有《读通鉴论》,自己读资治通鉴,如以上等等也是可以有所发挥成文的,谨记之以勉后续边读边有所产出。</p><p>《资治通鉴》已断断续续读了227卷,虽似懂非懂,读时多少亦有所想,很遗憾的是一直想记录但没有记录下只言片语,如:</p>
<ul>
<li>再读曹参时,才发现曹参深通黄老之术,有自知之明且不伐其功,是真正的大赢家,从韩信功高而不见盖主、随萧何无为而天下大治。</li>
<li>贾谊思想是如此的超前,感觉其思虑过重、见人之所未见是以以忧郁而死,而不是死在伤梁怀王之死。</li>
<li>东晋朝廷腐烂,江陵在南北朝时期的独特地位,王敦、桓温、桓玄等谋位未尝不可,成则刘裕、败则王敦、几成则桓玄。</li>
<li>魏孝文帝拓跋宏迁都、汉化的巨大魄力,是多大的勇气才能做到?</li>
<li>高欢、宇文泰的相爱相杀</li>
<li>唐高祖的历史功绩,没有李渊真能有唐?李渊在家族中的影响力,李渊的韬光养晦,忍一时之辱,李氏宗族子弟在开唐中的功绩。军攻虽李二居半,有李渊没有李二也有李三,没李渊真不一定有唐。</li>
<li>唐太宗纳谏之难</li>
<li>李辅国、鱼朝恩、程元振,为什么除了一个又生另一个甚至过犹不及,藩镇割据亦是?</li>
</ul>
<p>王夫之有《读通鉴论》,自己读资治通鉴,如以上等等也是可以有所发挥成文的,谨记之以勉后续边读边有所产出。</p>偏见(APP)永远的神2021-03-06T12:00:00+08:002021-03-06T12:00:00+08:00飞龙tag:feilong.me,2021-03-06:/2021/03/pianjian.html<p><img alt="pianjian" src="/static/2021/03-06-pianjian.jpg">
偏见是我创业时的一个副产品,在公司人员已流失、资源非常紧张的情况下仅用了一个月左右的时间开发的,但却是我创业项目里面算最成功的一个,在粉丝心中不死(如上图)。</p>
<p>偏见自我创业公司关停后仍然持续运营到2019年5月,因不断有通管局监管电联后关闭,心中实有万分不舍,但终被放弃。</p>
<p>偏见设计的很纯粹、功能非常简单,被18-用户当做一个情感倾诉的地方,虽然因为开发时间关系,bug较多很难用,但一点不减粉丝对它的喜爱,LOGO中一双转动的双眼似有说不完的故事。</p>
<p>偏见用户不止一次说到愿意赞助或众筹来支持偏见的运营和回归,足见他们对偏见的情感之深。过往我坚持不接受他们的赞助和众筹而用爱发电,回头看或许这是个错误,其不在于资金的多少,而在于勇敢地接下这幅担子,有此担子在身,我应有更大的勇气和毅力坚持下来,反过来也能更好的服务更多人为其提供偏见的产品价值,偏见的成功可能性又增一分。钱不只是阿堵物,合理的付出后获取合理的金钱也正是持续前进的砝码,尚缺这个觉悟。</p>
<p>附:<a href="https://mp.weixin.qq.com/s?__biz=MzU2ODk1NzMzOA==&mid=2247483722&idx=1&sn=07ea5c9b4d2e99dced5e8de8e14a7baf&chksm=fc8741bfcbf0c8a956f4e61e6225381b37800d520e6f18244af3f7a525402cda92465c8e7a3f&mpshare=1&scene=23&srcid=0915Blv5SRGZi45erCazypAL&sharer_sharetime=1614940070473&sharer_shareid=07e69f1580eedb8d3346b7f4a4d6846a%23rd">偏见,我们江湖再见</a></p>
<p>偏见停服了,但是我们的故事还未完结,偏见的小伙伴们心里都有一个小角落,那儿堆满了偏见的美好回忆,开心的、欢笑的、苦闷的、拌嘴的、玩闹的。我们都相信偏见总有一天会想南归的大雁,回到我们身边。</p>
<p>沈从文,岑桑,牛顿的橘子,蜜桃居居,whisper,囍囍 …</p><p><img alt="pianjian" src="/static/2021/03-06-pianjian.jpg">
偏见是我创业时的一个副产品,在公司人员已流失、资源非常紧张的情况下仅用了一个月左右的时间开发的,但却是我创业项目里面算最成功的一个,在粉丝心中不死(如上图)。</p>
<p>偏见自我创业公司关停后仍然持续运营到2019年5月,因不断有通管局监管电联后关闭,心中实有万分不舍,但终被放弃。</p>
<p>偏见设计的很纯粹、功能非常简单,被18-用户当做一个情感倾诉的地方,虽然因为开发时间关系,bug较多很难用,但一点不减粉丝对它的喜爱,LOGO中一双转动的双眼似有说不完的故事。</p>
<p>偏见用户不止一次说到愿意赞助或众筹来支持偏见的运营和回归,足见他们对偏见的情感之深。过往我坚持不接受他们的赞助和众筹而用爱发电,回头看或许这是个错误,其不在于资金的多少,而在于勇敢地接下这幅担子,有此担子在身,我应有更大的勇气和毅力坚持下来,反过来也能更好的服务更多人为其提供偏见的产品价值,偏见的成功可能性又增一分。钱不只是阿堵物,合理的付出后获取合理的金钱也正是持续前进的砝码,尚缺这个觉悟。</p>
<p>附:<a href="https://mp.weixin.qq.com/s?__biz=MzU2ODk1NzMzOA==&mid=2247483722&idx=1&sn=07ea5c9b4d2e99dced5e8de8e14a7baf&chksm=fc8741bfcbf0c8a956f4e61e6225381b37800d520e6f18244af3f7a525402cda92465c8e7a3f&mpshare=1&scene=23&srcid=0915Blv5SRGZi45erCazypAL&sharer_sharetime=1614940070473&sharer_shareid=07e69f1580eedb8d3346b7f4a4d6846a%23rd">偏见,我们江湖再见</a></p>
<p>偏见停服了,但是我们的故事还未完结,偏见的小伙伴们心里都有一个小角落,那儿堆满了偏见的美好回忆,开心的、欢笑的、苦闷的、拌嘴的、玩闹的。我们都相信偏见总有一天会想南归的大雁,回到我们身边。</p>
<p>沈从文,岑桑,牛顿的橘子,蜜桃居居,whisper,囍囍,聂怂怂,甜甜,鸭梨山大,恋林雪,山狸,球来,阿陌,直言,慕流年,13,秃顶老仙女,果冻,山鬼来了,瘐谋,阿卓,楠先生,基遇,买了否冷,破茧,綦灯....偏见的小伙伴啊,虽然还有好多好多名字我没有打出来,但是你们一定都在我们的心里存在过。</p>
<p>偏见再见了,希望再相遇的我们仍是少年。</p>有所为,何所为?2021-03-05T12:00:00+08:002021-03-05T12:00:00+08:00飞龙tag:feilong.me,2021-03-05:/2021/03/what-to-do.html<p>人生在世,当有所为。</p>
<p>回顾过往,雄心万丈,有想法,有行动,但没有坚持,深以为憾。
尝试过的项目历历在目,项目没有坚持下来,其原因虽各不同,但必有其共同之处,需深刻反思。</p>
<ul>
<li>如立项之初就带有玩票性质,没有很明确的目标的(如 haizai.org 17weiguan.com),其必不可能长久;</li>
<li>china-4s.com非出于自己的想法,项目认可度不够;</li>
<li>掌游圈可为,但非自己可支配的资源所能为,当为网易大神之类之地盘;</li>
</ul>
<p>这些都应只是表面上的原因,其更深刻的原因应该在于对产品方向的热爱不够且自身意志力不够,需要修身上再有所提升。</p>
<p>纵观一下我做的事情如:</p>
<ul>
<li>开源poweredsites.org tornadogists.org帮助别人学Tornado</li>
<li>chinapy.org回答别人Python问题</li>
<li>偏见APP则提供了一个小年轻的倾诉通道</li>
</ul>
<p>发现我还是非常乐于帮助他人的,而且从中获得的成就感比较强烈,这是可能的可坚持的动力源泉之一。</p><p>人生在世,当有所为。</p>
<p>回顾过往,雄心万丈,有想法,有行动,但没有坚持,深以为憾。
尝试过的项目历历在目,项目没有坚持下来,其原因虽各不同,但必有其共同之处,需深刻反思。</p>
<ul>
<li>如立项之初就带有玩票性质,没有很明确的目标的(如 haizai.org 17weiguan.com),其必不可能长久;</li>
<li>china-4s.com非出于自己的想法,项目认可度不够;</li>
<li>掌游圈可为,但非自己可支配的资源所能为,当为网易大神之类之地盘;</li>
</ul>
<p>这些都应只是表面上的原因,其更深刻的原因应该在于对产品方向的热爱不够且自身意志力不够,需要修身上再有所提升。</p>
<p>纵观一下我做的事情如:</p>
<ul>
<li>开源poweredsites.org tornadogists.org帮助别人学Tornado</li>
<li>chinapy.org回答别人Python问题</li>
<li>偏见APP则提供了一个小年轻的倾诉通道</li>
</ul>
<p>发现我还是非常乐于帮助他人的,而且从中获得的成就感比较强烈,这是可能的可坚持的动力源泉之一。</p>看《毛骗》有感2021-03-04T12:00:00+08:002021-03-04T12:00:00+08:00飞龙tag:feilong.me,2021-03-04:/2021/03/maopian.html<p>最近无意中在知乎发现了《毛骗》这部草根神剧,一口气刷完三季,刷完感慨最多的不是剧情,而是《毛骗》这个创作团队的坚持与不易。</p>
<p>毫不夸张的说,《毛骗》第一季除了剧情外,演技、场景、道具、拍摄手法、剪辑、音效等等都是渣渣,小宝的杀马特风、不忍卒睹的赞助广告、毫无演技的演技,约饭饭局磕碜土豆丝、烟盒手机、一部DV抖动拍全剧等均在说明这个剧组是有多穷,资源是有多捉襟见肘,但是在这样的条件下一群20来岁的三线大学生在一个三线城市却拍出来神级网剧,豆瓣对三季的评分节节高,终结篇更高达9.7分。他们无疑是成功的,是有值得学习的地方,对比自己顿觉汗颜,因此我更愿意透过剧集来看他们的创业闪光点:</p>
<ul>
<li>
<p>见贤思齐,先学会模仿。据豆瓣网友说第一季剧情严重抄袭英剧《Hustle》,虽然我没有看过《Hustle》(后面有机会补),但看到有大量网友鄙视此事,抄袭一事应该是真的不可否认,据此我猜想创作团队拍摄本片的起因也正是因为看到了《Hustle》,出于对《Hustle》喜爱才萌发拍一个本土化的版本的念头,他们没有停步于欣赏上,而是付诸于实际行动,草台班子搭了起来,从模仿开始拍出来第一季 …</p></li></ul><p>最近无意中在知乎发现了《毛骗》这部草根神剧,一口气刷完三季,刷完感慨最多的不是剧情,而是《毛骗》这个创作团队的坚持与不易。</p>
<p>毫不夸张的说,《毛骗》第一季除了剧情外,演技、场景、道具、拍摄手法、剪辑、音效等等都是渣渣,小宝的杀马特风、不忍卒睹的赞助广告、毫无演技的演技,约饭饭局磕碜土豆丝、烟盒手机、一部DV抖动拍全剧等均在说明这个剧组是有多穷,资源是有多捉襟见肘,但是在这样的条件下一群20来岁的三线大学生在一个三线城市却拍出来神级网剧,豆瓣对三季的评分节节高,终结篇更高达9.7分。他们无疑是成功的,是有值得学习的地方,对比自己顿觉汗颜,因此我更愿意透过剧集来看他们的创业闪光点:</p>
<ul>
<li>
<p>见贤思齐,先学会模仿。据豆瓣网友说第一季剧情严重抄袭英剧《Hustle》,虽然我没有看过《Hustle》(后面有机会补),但看到有大量网友鄙视此事,抄袭一事应该是真的不可否认,据此我猜想创作团队拍摄本片的起因也正是因为看到了《Hustle》,出于对《Hustle》喜爱才萌发拍一个本土化的版本的念头,他们没有停步于欣赏上,而是付诸于实际行动,草台班子搭了起来,从模仿开始拍出来第一季,这听起来跟Copy to China的互联网创业故事如出一辙,模仿并不可耻,向领先者学习、从临摹开始是一个书法家、画家等各种家成功的必经之路。</p>
</li>
<li>
<p>坚持。毛骗第二季共14集的播出断断续续从2011-10-20持续到2014-01-05,近两年多的时间才产出14集,这过程的艰辛可想而知,资金筹措(真的穷极)、剧本创作(跳出《Hustle》框框,自主创作)、演员统筹(如赵宁个人原因离开石家庄、黎伟在北京等),说这过程中他们没有想过放弃或者烂尾我是不相信的,哪怕是一而再再而三的跳票,最终他们坚持了下来。第二季摘掉了抄袭的帽子、团队演技逐步成熟上线、剧情布局宏大,本季品质直接上了一个台阶,是离不开他们的坚持的。</p>
</li>
<li>
<p>是什么让他们坚持了下来?固然有个人和团队的优秀品质在起作用,先应下来(续拍)再说和外部粉丝的推动应该都起到了很大的作用。在《Personal Development for Smart People》一书中有提到“先应下来再说”这一策略的威力,在勇敢的应下来之后排除万难去达成,有点置之死地而后生的味道。第一季的播出让团队有了一批粉丝,外部粉丝的催更也促使了团队不得不坚持,坚持写公众号的作者似与此同。我自己的多个创业项目或产品,之所以未能成功,绝不在于产品方向、绝不在于时间点、绝不在于技术高低和团队的强弱,而在于最终没有坚持,其原因有我个人的勇气不够在,也有没有制造出足够的内压和外压环境在,这点需要持续的反思和改进。</p>
</li>
<li>
<p>成长。1-3季看下来可以很欣慰的看到这个团队逐步的成长,演技的精进、剧情的丰富、团队的壮大、引资的增加等等,就像剧集里团队的进步一样,短短的几年时间里处处可见场外创作团队的进步,日进一步积千里。</p>
</li>
</ul>
<p>看《毛骗》除了欣赏剧情以外,跳出来看《毛骗》创作团队的创业,也是非常值得学习的。</p>
<p>附:毛骗专访<br>
<a href="https://movie.douban.com/review/7606684/">https://movie.douban.com/review/7606684/</a><br>
<a href="https://www.sohu.com/a/154603038_436725">https://www.sohu.com/a/154603038_436725</a></p>
<blockquote>
<p>冬冬:最有压力的时候就是差点吃不上饭。当时有个项目流产,导致资金短缺,然而当时由于没什么经验也没后备项目,顿时陷入经济危机。李洪绸导演后来找朋友借了两万块钱启动了《毛骗》的拍摄。那时只有一台摄像机一个话筒一个三脚架。这就是毛骗最初的设备。出外景拍戏基本上靠坐公交,打的都觉得是罪过。但那时候大家并没有觉得苦,每天反而很快乐,就这么不知不觉的走到了现在。</p>
<p>《毛骗》第一季也的确获得了好评,但当时网络视频混沌初开,人气并没有转化成为实质的东西,第二季做起来更为吃力。为了生计,李洪绸不得不抽出空来,拍一些电视台的栏目剧和网络广告,又为了维持人气,拍摄了另一部低成本的情景喜剧《麻辣隔壁》。</p>
<p>《毛骗•贰》是在这期间穿插着拍的,2011年到2013年,三年才拍了十四集。这期间我一度非常迷茫,一边跟团队的小伙伴打鸡血,说我坚信网络视频将来一定能发展起来,网络剧也一定会成为市场的宠儿,一边又是举步维艰的现实。更重要的是,用数年时间去做一个剧集,大家显得有些‘疲’了”,李洪绸回忆道,“终于,2013年底到2014年初,网络剧开始起来了,有个制片人找到我,说很喜欢我们的《毛骗》,希望我能拍完这个片子,我随口报了一个预算,她马上就答应了。于是,我们开始了《毛骗•终结篇》的拍摄,给观众一个交待。</p>
<p>当然,对我们来说,《毛骗》之难忘,不是说它口碑如何如何,而是我们花了五年去做这么一部剧,那是我们正值青春的五年,是我们激情洋溢的五年,是我们相互扶持的五年。虽然当时觉得日子艰难,但现在回想,却是非常美好的一段时光。所以我经常提醒身边的朋友,不要埋怨当下的种种不理想,任何一个当下都是未来的过去,只要过去了,你总会有所怀念,总能找到很多美好</p>
</blockquote>《道德经》中的”无为管理“思想2020-06-01T12:00:00+08:002020-06-01T12:00:00+08:00飞龙tag:feilong.me,2020-06-01:/2020/06/laozi-wuwei.html<p>《道德经》中的”无为管理“思想</p>
<p>《道德经》上下篇仅仅五千言,却是中国历史上最伟大的名著之一,是道家哲学思想的重要来源。除了论述修身、治国、用兵、养生之道之外,《道德经》中也包含了丰富的教学管理思想,张朋老师重点提到了“无为管理、虚其心、实其腹”等,而“无为管理”的思想是贯穿《道德经》始终的一个核心思想。</p>
<p>“无为”不是真的就无所作为,而是“不妄为”、“为之于未有”,是从细微处、从根基出做起,是遵循万物的本质、规律而不妄加干预,是抓住孩子们尚处于萌芽中的好苗头而顺势而为。</p>
<p>我的女儿打小我让她尝试课外学习画画、弹钢琴、跳舞、轮滑、围棋等,但对这些我的态度都是先让她体验一段时间,后看她自己对这些事情的长期兴趣是否还在。弹钢琴她刚开始十天半个月兴趣是挺大的,我们还特意买了一架钢琴放家里方便她练习,但是随着时间的推移我们发现这几项里面她自己最感兴趣的还是画画,除了课外班上课之外,她自己时不时的会画张贺卡祝贺妈妈生日快乐、看到什么有趣的卡通画面学着临摹下来、画个小动物什么的逗弟弟玩,这是她自发的很好的一个苗头,因此我们决定不因买了钢琴就强行要求她坚持弹钢琴 …</p><p>《道德经》中的”无为管理“思想</p>
<p>《道德经》上下篇仅仅五千言,却是中国历史上最伟大的名著之一,是道家哲学思想的重要来源。除了论述修身、治国、用兵、养生之道之外,《道德经》中也包含了丰富的教学管理思想,张朋老师重点提到了“无为管理、虚其心、实其腹”等,而“无为管理”的思想是贯穿《道德经》始终的一个核心思想。</p>
<p>“无为”不是真的就无所作为,而是“不妄为”、“为之于未有”,是从细微处、从根基出做起,是遵循万物的本质、规律而不妄加干预,是抓住孩子们尚处于萌芽中的好苗头而顺势而为。</p>
<p>我的女儿打小我让她尝试课外学习画画、弹钢琴、跳舞、轮滑、围棋等,但对这些我的态度都是先让她体验一段时间,后看她自己对这些事情的长期兴趣是否还在。弹钢琴她刚开始十天半个月兴趣是挺大的,我们还特意买了一架钢琴放家里方便她练习,但是随着时间的推移我们发现这几项里面她自己最感兴趣的还是画画,除了课外班上课之外,她自己时不时的会画张贺卡祝贺妈妈生日快乐、看到什么有趣的卡通画面学着临摹下来、画个小动物什么的逗弟弟玩,这是她自发的很好的一个苗头,因此我们决定不因买了钢琴就强行要求她坚持弹钢琴,不在弹钢琴这件事情上忘为,而是遵循孩子的真实兴趣,继续在画画上给她创造更好的学习条件,让她自己顺着自己的兴趣点下去发挥,这或许正是老子的“无为管理”的思想在我教育孩子中的体现吧。</p>《孙子兵法》的先胜后战思想2019-03-29T12:00:00+08:002019-03-29T12:00:00+08:00飞龙tag:feilong.me,2019-03-29:/2019/03/win-at-first.html<p>孙子开篇讲“计”,这里的计不同于三十六计的计,三十六计的“计”是奇谋巧计,是阴谋诡计;《孙子兵法》的计,不是用计,不是奇谋巧计,而是计算的计,是讲计算,不是讲计谋。</p>
<p>杜牧注:</p>
<blockquote>
<p>计,算也。曰:计算何事?曰:下之五事,所谓道、天、地、将、法也。于庙堂之上,先以彼我之五事计算优劣,然后定胜负。胜负既定,然后兴师动众。用兵之道,莫先此五事,故为首篇耳。</p>
</blockquote>
<p>孙子的“计”,是计算实力的对比,对比计算的,书中有谈到五项,叫“五事七计”。五事,是道、天、地、将、法。七计,是主孰有道、将孰有能 …</p><p>孙子开篇讲“计”,这里的计不同于三十六计的计,三十六计的“计”是奇谋巧计,是阴谋诡计;《孙子兵法》的计,不是用计,不是奇谋巧计,而是计算的计,是讲计算,不是讲计谋。</p>
<p>杜牧注:</p>
<blockquote>
<p>计,算也。曰:计算何事?曰:下之五事,所谓道、天、地、将、法也。于庙堂之上,先以彼我之五事计算优劣,然后定胜负。胜负既定,然后兴师动众。用兵之道,莫先此五事,故为首篇耳。</p>
</blockquote>
<p>孙子的“计”,是计算实力的对比,对比计算的,书中有谈到五项,叫“五事七计”。五事,是道、天、地、将、法。七计,是主孰有道、将孰有能、天地孰得、法令孰行、兵众孰强、士卒孰练、赏罚孰明。就是比较敌我双方的政治、天时、地利、人才和法治。计的目的是什么呢?是为了知胜。比较这五个方面,七个科目,在战前就能判断胜负。计算比较后,就知道有没有“胜算”。是谓:“夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也。多算胜,少算不胜,而况于无算乎!吾以此观之,胜负见矣。”</p>
<p>孙子进而在第四篇“军行篇”更明确提出“是故胜兵先胜而后求战,败兵先战而后求胜。”的先胜后战的思想。“先胜而后求战”就是在了解彼此强弱胜负之情的基础上,有充分的应敌准备,“先为不可胜,以待敌之可胜”,使自己立于不败之地,有把握的取胜而后求战,反对那种既不做周密考虑,又盲目自信轻敌的“先战而后求胜”的错误做法。</p>
<p>落到我们做产品上,对大的产品方向和未来的产品形态我们必须结合当前行业发展趋势、产品特性、用户群体特征、公司资源、团队现状等等各方面先做好充分的研究,做到先算、先充分的算,之后我们才可能找到一条正确的产品可行性的方向,然后求战着手开发和运营产品,只有这样踩在一条正确的道上,先胜而后求战我们才能够立于不败之地取得成功。</p>作恶的IT培训机构2018-11-30T12:00:00+08:002018-11-30T12:00:00+08:00飞龙tag:feilong.me,2018-11-30:/2018/11/do-not-be-evil.html<p>最近有位朋友找我帮他的小弟介绍工作,简历上写着两年的Java开发经验,各种“熟练掌握”Java相关,而线下聊下来发现他之前从事化工行业,无任何IT行业从业背景,简历上写的项目经验实际上是他最近五个月在IT培训机构上的DEMO作业,问了一些前后端相关的知识后,可以判断他简历上所说的“熟练”只能算“知道”有这么个东西,甚至连皮毛都还不知道。</p>
<p>他简历何以敢夸大实情、虚报项目经验,原是IT培训机构教唆使然,他跟我说培训机构的老师给了他们简历模板,“教”他们这么写、“教”他们刷面试题,告诉他们这样写才有跟多的面试机会、更大的录取机会,从培训机构的角度来看这貌似也很有道理,这可能侥幸提升他们的学员就业率,但可能就坑了用人单位、坑了学员。IT培训机构为了提升学员就业率本无可厚非,但是不想着在如何提升师资力量、提升课程教材质量、跟紧技术发展潮流、引入真实的工程项目等硬实力上提升功夫,却玩起了奇淫技巧琢磨着如何包装学员、如何弄虚作假,这就本末倒置了。</p>
<p>几乎所有的公司都会把诚信问题列为公司的高压线,只要发现有虚假学历、虚假工作经验、虚假报销等弄虚作假的行为,大都会毫不手软的予以辞退甚至追求法律责任,这样作恶的IT培训机构自己作恶还教学员作恶,真是十分可恶,好好的IT培训行业被搅成一锅粥,难怪前些年郝培强要写博客说<a href="http://itindex.net/detail/5867-%E6%8B%9B%E8%81%98-%E6%92%AD%E5%AE%A2-%E5%AD%A6%E7%94%9F">“为什么我们招聘的时候绝不要传智播客的学生”</a>。(备注:传智播客为一家IT培训机构)。</p>
<p>不是说IT培训机构出来的就没一个好学员 …</p><p>最近有位朋友找我帮他的小弟介绍工作,简历上写着两年的Java开发经验,各种“熟练掌握”Java相关,而线下聊下来发现他之前从事化工行业,无任何IT行业从业背景,简历上写的项目经验实际上是他最近五个月在IT培训机构上的DEMO作业,问了一些前后端相关的知识后,可以判断他简历上所说的“熟练”只能算“知道”有这么个东西,甚至连皮毛都还不知道。</p>
<p>他简历何以敢夸大实情、虚报项目经验,原是IT培训机构教唆使然,他跟我说培训机构的老师给了他们简历模板,“教”他们这么写、“教”他们刷面试题,告诉他们这样写才有跟多的面试机会、更大的录取机会,从培训机构的角度来看这貌似也很有道理,这可能侥幸提升他们的学员就业率,但可能就坑了用人单位、坑了学员。IT培训机构为了提升学员就业率本无可厚非,但是不想着在如何提升师资力量、提升课程教材质量、跟紧技术发展潮流、引入真实的工程项目等硬实力上提升功夫,却玩起了奇淫技巧琢磨着如何包装学员、如何弄虚作假,这就本末倒置了。</p>
<p>几乎所有的公司都会把诚信问题列为公司的高压线,只要发现有虚假学历、虚假工作经验、虚假报销等弄虚作假的行为,大都会毫不手软的予以辞退甚至追求法律责任,这样作恶的IT培训机构自己作恶还教学员作恶,真是十分可恶,好好的IT培训行业被搅成一锅粥,难怪前些年郝培强要写博客说<a href="http://itindex.net/detail/5867-%E6%8B%9B%E8%81%98-%E6%92%AD%E5%AE%A2-%E5%AD%A6%E7%94%9F">“为什么我们招聘的时候绝不要传智播客的学生”</a>。(备注:传智播客为一家IT培训机构)。</p>
<p>不是说IT培训机构出来的就没一个好学员,但是因为有IT培训机构作恶的案例在,而且类似的事件并不鲜见,这也提醒我们在招聘人员的时候要擦亮眼睛,不要为简历所蒙蔽,多方面考察其真才实学,对候选者做成相对准确的判断以最好的量才用人。</p>You can you up!2018-06-28T12:00:00+08:002018-06-28T12:00:00+08:00飞龙tag:feilong.me,2018-06-28:/2018/06/you-can-you-up.html<p>读《资治通鉴》读到邓芝使吴的故事,不禁令人拍案叫绝:</p>
<blockquote>
<p>汉尚书义阳邓芝言于诸葛亮曰:“今主上幼弱,初即尊位,宜遣大使重申吴好。”亮曰:“吾思之久矣,未得其人耳,今日始得之。”芝问:“其人为谁?”亮曰:“即使君也。”乃遣芝以中郎将修好于吴。冬,十月,芝至吴。时吴王犹未与魏绝,狐疑,不时见芝。芝乃自表请见曰:“臣今来,亦欲为吴,非但为蜀也。”吴王见之,曰:“孤诚愿与蜀和亲,然恐蜀主幼弱,国小势逼,为魏所乘,不自保全耳。”芝对曰:“吴、蜀二国,四州之地。大王命世之英,诸葛亮亦一时之杰也;蜀有重险之固,吴有三江之阻。合此二长,共为脣齿,进可并兼天下,退可鼎足而立,此理之自然也。大王今若委质于魏,魏必上望大王之入朝,下求太子之内侍 …</p></blockquote><p>读《资治通鉴》读到邓芝使吴的故事,不禁令人拍案叫绝:</p>
<blockquote>
<p>汉尚书义阳邓芝言于诸葛亮曰:“今主上幼弱,初即尊位,宜遣大使重申吴好。”亮曰:“吾思之久矣,未得其人耳,今日始得之。”芝问:“其人为谁?”亮曰:“即使君也。”乃遣芝以中郎将修好于吴。冬,十月,芝至吴。时吴王犹未与魏绝,狐疑,不时见芝。芝乃自表请见曰:“臣今来,亦欲为吴,非但为蜀也。”吴王见之,曰:“孤诚愿与蜀和亲,然恐蜀主幼弱,国小势逼,为魏所乘,不自保全耳。”芝对曰:“吴、蜀二国,四州之地。大王命世之英,诸葛亮亦一时之杰也;蜀有重险之固,吴有三江之阻。合此二长,共为脣齿,进可并兼天下,退可鼎足而立,此理之自然也。大王今若委质于魏,魏必上望大王之入朝,下求太子之内侍,若不从命,则奉辞伐叛,蜀亦顺流见可而进。如此,江南之地非复大王之有也。”吴王默然良久曰:“君言是也。”遂绝魏,专与汉连和。</p>
</blockquote>
<p>在关羽、刘备相继被东吴击败,幼主刘禅继位之后,急于改善与吴国的邦交关系的诸葛亮果断的让提出“重申吴好”建议的邓芝使吴,真是一代大师的风范。可想而知邓芝在提出使吴的建议前,对此事已有一番自己的深思熟虑,出使东吴,邓芝是再合适不过的人选,后面吴蜀重修旧好自是水到渠成的结果。</p>
<p>如何挖掘、培养和用对人才永远考验管理者的重要课题,谁提出的问题就交给谁干,看似粗暴实际却行之有效。团队里遇到问题,一但有类似于邓芝这样的有想法的人冒出来,一定要果敢的把事情交给他(他)来做,大胆的说:“You can you up!”,必有奇效。</p>知非改过,不二过2018-05-29T12:00:00+08:002018-05-29T12:00:00+08:00飞龙tag:feilong.me,2018-05-29:/2018/05/never-fail-again.html<p>孔子多次盛赞自己的弟子颜回,其中重要的一点是颜回“不迁怒,不二过”,这六字看似极平常,却极难做到。</p>
<p>我闺女的作业平时主要是孩子妈在管,最近孩子妈抱怨说孩子的数学作业老是出现上下文数字抄错、加减计算错误等明显的问题,让我看看到底什么原因。我仔细检查了她的作业后发现确实都是些非常低级的错误,要她当场找出自己的错误所在,其实她很容易做到,但下次作业还是会犯同样的错。如果她做完作业以后再仔细检查一遍的话,很多错误本可以避免,错误的本身不在于一次抄写、一次计算,而在于没有深刻反省自己的错误、认识到自己在哪些情况下容易犯错、没有掌握避免犯同样错误的解决办法。这种情况我自己也深有体会,以前读书考试,匆匆忙忙赶时间做完卷子之后,不可避免也会有些小错,但在考试时间结束之前,会仔仔细细的多做检查,对于自己常犯错的点平时要善于总结,考试时对此类问题更是慎之又慎,尽最大可能减小出错的可能,只有学会复查才能避免考试犯同样的错误。</p>
<p>生活中也类似,我们每天都可能会犯或这或那的各式错误,所以我们需要学会“吾日三省吾身”,来反思自己做的不对的地方,《了凡四训》中说“务要日日知非,日日改过。一日不知非,即一日安于自是。一日无过可改,即一日无步可进。天下聪明俊秀不少,所以德不加修,业不加广者,只为因循二字耽阁一生。”诚至理名言。</p>
<p>要做到颜回的 …</p><p>孔子多次盛赞自己的弟子颜回,其中重要的一点是颜回“不迁怒,不二过”,这六字看似极平常,却极难做到。</p>
<p>我闺女的作业平时主要是孩子妈在管,最近孩子妈抱怨说孩子的数学作业老是出现上下文数字抄错、加减计算错误等明显的问题,让我看看到底什么原因。我仔细检查了她的作业后发现确实都是些非常低级的错误,要她当场找出自己的错误所在,其实她很容易做到,但下次作业还是会犯同样的错。如果她做完作业以后再仔细检查一遍的话,很多错误本可以避免,错误的本身不在于一次抄写、一次计算,而在于没有深刻反省自己的错误、认识到自己在哪些情况下容易犯错、没有掌握避免犯同样错误的解决办法。这种情况我自己也深有体会,以前读书考试,匆匆忙忙赶时间做完卷子之后,不可避免也会有些小错,但在考试时间结束之前,会仔仔细细的多做检查,对于自己常犯错的点平时要善于总结,考试时对此类问题更是慎之又慎,尽最大可能减小出错的可能,只有学会复查才能避免考试犯同样的错误。</p>
<p>生活中也类似,我们每天都可能会犯或这或那的各式错误,所以我们需要学会“吾日三省吾身”,来反思自己做的不对的地方,《了凡四训》中说“务要日日知非,日日改过。一日不知非,即一日安于自是。一日无过可改,即一日无步可进。天下聪明俊秀不少,所以德不加修,业不加广者,只为因循二字耽阁一生。”诚至理名言。</p>
<p>要做到颜回的“不二过”太难,至少我们应该及时反省自己,总结以往的错误,不要一而再再而三的犯类似的错误。</p>解决Kindle上PDF不能正常显示的问题2017-11-14T12:00:00+08:002017-11-14T12:00:00+08:00飞龙tag:feilong.me,2017-11-14:/2017/11/pdf2imgpdf-pdf2img-img2pdf.html<p>我平时用Kindle看书较多,遇到了一些PDF文件在Kindle上不能正常显示的问题,这类问题通常是因为PDF源文件里用了一些特殊字体或是一些扫描版的PDF,常见的现象是乱码或页面一片漆黑。</p>
<p>在Mac上有一个很讨巧的方法解决这个问题,用Mac自带的Preview的Export as PDF功能,将PDF源文件导出为一个新的PDF文件,Preview大致的原理就是将打开的Word、PPT、Excel、JPG、PNG、PDF等格式文件都视为或转为一页页的图片,然后以图片作为新的PDF的每一页的内容,因为是标准的图片所以到哪都能正确显示。但是,很不幸的是Preview在转换一些PDF文件的时候会无响应,搜索Preview export hang up或crash,发现吐槽这个问题的不止我一个,于是想用Python是否能解决下这个问题,参考了网上的一些实现,考察了多个库的实现方案后,找到了解决办法:</p>
<h3>首先,将PDF转成一张张的图片</h3>
<p>主要参考了<a href="https://gist.github.com/jrsmith3/9947838">Convert specified pages from a PDF to png</a>,系统需要装imagemagick、ghostscript,Python需要<a href="https://github.com/dahlia/wand">wand</a>、<a href="https://github.com/mstamy2/PyPDF2">PyPDF2</a>两个库:</p>
<div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">pdf2img</span><span class="p">(</span><span class="n">src_pdf</span><span class="p">,</span> <span class="n">pagenum</span><span class="o">=</span><span class="mi">0 …</span></pre></div><p>我平时用Kindle看书较多,遇到了一些PDF文件在Kindle上不能正常显示的问题,这类问题通常是因为PDF源文件里用了一些特殊字体或是一些扫描版的PDF,常见的现象是乱码或页面一片漆黑。</p>
<p>在Mac上有一个很讨巧的方法解决这个问题,用Mac自带的Preview的Export as PDF功能,将PDF源文件导出为一个新的PDF文件,Preview大致的原理就是将打开的Word、PPT、Excel、JPG、PNG、PDF等格式文件都视为或转为一页页的图片,然后以图片作为新的PDF的每一页的内容,因为是标准的图片所以到哪都能正确显示。但是,很不幸的是Preview在转换一些PDF文件的时候会无响应,搜索Preview export hang up或crash,发现吐槽这个问题的不止我一个,于是想用Python是否能解决下这个问题,参考了网上的一些实现,考察了多个库的实现方案后,找到了解决办法:</p>
<h3>首先,将PDF转成一张张的图片</h3>
<p>主要参考了<a href="https://gist.github.com/jrsmith3/9947838">Convert specified pages from a PDF to png</a>,系统需要装imagemagick、ghostscript,Python需要<a href="https://github.com/dahlia/wand">wand</a>、<a href="https://github.com/mstamy2/PyPDF2">PyPDF2</a>两个库:</p>
<div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">pdf2img</span><span class="p">(</span><span class="n">src_pdf</span><span class="p">,</span> <span class="n">pagenum</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="s2">"filename"</span><span class="p">,</span> <span class="n">resolution</span><span class="o">=</span><span class="mi">600</span><span class="p">):</span>
<span class="n">dst_pdf</span> <span class="o">=</span> <span class="n">PdfFileWriter</span><span class="p">()</span>
<span class="n">dst_pdf</span><span class="o">.</span><span class="n">addPage</span><span class="p">(</span><span class="n">src_pdf</span><span class="o">.</span><span class="n">getPage</span><span class="p">(</span><span class="n">pagenum</span><span class="p">))</span>
<span class="n">pdf_bytes</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">()</span>
<span class="n">dst_pdf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pdf_bytes</span><span class="p">)</span>
<span class="n">pdf_bytes</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">with</span> <span class="n">Image</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="n">pdf_bytes</span><span class="p">,</span> <span class="n">resolution</span><span class="o">=</span><span class="n">resolution</span><span class="p">)</span> <span class="k">as</span> <span class="n">img</span><span class="p">:</span>
<span class="n">img</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s2">"png"</span><span class="p">)</span>
<span class="n">img</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="n">filename</span><span class="p">)</span>
</pre></div>
<p>其原理是用PyPDF2取出PDF的某一页,作为一个新的只有一页的PDF,写到一个BytesIO流中,再由wand库去读这个单页PDF中的内容生成一个图片文件,导出的图片和源PDF页面的内容一致,其中resolution的大小直接决定了导出的图片的画质,建议在300以上。</p>
<p>这里很有意思的是,我在转页数比较多的PDF的时候,发现Python占用的内存疯长,用<a href="https://pypi.python.org/pypi/memory_profiler">memory_profiler</a>看了下,每转一个文件大概涨50M内存,问题出在<code>img.save</code>这一步,进一步发现是imagemagick的内存泄露,搜索imagemagick memory leak的问题也很多,这里就不再展开。</p>
<h3>然后,图片再转回PDF</h3>
<p>我先试了<a href="https://github.com/Setasign/FPDF">FPDF</a>这个库,FPDF可以实现,但:</p>
<ol>
<li>FPDF输入的图片大小必须和PDF的页面大小一致,如A4大小的PDF,图片宽高为(595.28, 841.89),需要对图片做一次resize,画质非常受影响。</li>
<li>不管前一步生成的是PNG还是JPEG格式的图片,用FPDF合成的PDF文件都特别很大,以我试的文件为例,从原PDF转完生成新的PDF大约大了10倍。</li>
<li>合成速度比较慢</li>
</ol>
<p>对FPDF画质不满意,后来我又试了下<a href="https://pypi.python.org/pypi/img2pdf/0.2.4">img2pdf</a>,关键的就<code>img2pdf.convert(imgs, layout_fun=layout_fun)</code>这么一句,layout_fun是为了设置A4大小的PDF格式。</p>
<p>简单的转一个PDF文件的代码如下:</p>
<div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">convert</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dest</span><span class="p">):</span>
<span class="c1"># specify paper size (A4)</span>
<span class="n">src</span> <span class="o">=</span> <span class="n">escape</span><span class="o">.</span><span class="n">to_unicode</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
<span class="n">dest</span> <span class="o">=</span> <span class="n">escape</span><span class="o">.</span><span class="n">to_unicode</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
<span class="n">a4inpt</span> <span class="o">=</span> <span class="p">(</span><span class="n">img2pdf</span><span class="o">.</span><span class="n">mm_to_pt</span><span class="p">(</span><span class="mi">210</span><span class="p">),</span> <span class="n">img2pdf</span><span class="o">.</span><span class="n">mm_to_pt</span><span class="p">(</span><span class="mi">297</span><span class="p">))</span>
<span class="n">layout_fun</span> <span class="o">=</span> <span class="n">img2pdf</span><span class="o">.</span><span class="n">get_layout_fun</span><span class="p">(</span><span class="n">a4inpt</span><span class="p">)</span>
<span class="n">src_pdf</span> <span class="o">=</span> <span class="n">PdfFileReader</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
<span class="n">num_pages</span> <span class="o">=</span> <span class="n">src_pdf</span><span class="o">.</span><span class="n">getNumPages</span><span class="p">()</span>
<span class="n">imgs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">des_pdf</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">num_pages</span><span class="p">):</span>
<span class="n">filename</span> <span class="o">=</span> <span class="s2">"/tmp/page-</span><span class="si">%s</span><span class="s2">-</span><span class="si">%s</span><span class="s2">.png"</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">)</span>
<span class="n">imgs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="n">pdf2img</span><span class="p">(</span><span class="n">src_pdf</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
<span class="n">des_pdf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">img2pdf</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="n">imgs</span><span class="p">,</span> <span class="n">layout_fun</span><span class="o">=</span><span class="n">layout_fun</span><span class="p">))</span>
<span class="k">for</span> <span class="n">filename</span> <span class="ow">in</span> <span class="n">imgs</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> converted to </span><span class="si">%s</span><span class="s2"> !"</span> <span class="o">%</span> <span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dest</span><span class="p">))</span>
</pre></div>
<p>相比FPDF,img2pdf更优:</p>
<ol>
<li>img2pdf不受图片尺寸限制,可以使用较高的resolution获得清晰的画质,生成的PDF清晰。</li>
<li>图片若采用PNG格式,img2pdf转后的PDF文件很小,以我试的PDF文件为例,resolution设为600时,用PNG格式时大约是源PDF的两倍,而用JPG格式的话,大约是20倍,不可接受。</li>
<li>img2pdf的速度也很快,赞!</li>
</ol>
<p>我一直在读《资治通鉴》,最近找到一版极好的影印版PDF,但在Kindle上PDF全黑看不了,困扰了我几天,终于一言不合就写代码,问题得到完美解决。</p>
<p>代码已开源出来,或许你也能用上 <a href="https://github.com/felinx/pdf2imgpdf">pdf2imgpdf</a></p>“学而时习之”何解?2017-10-26T12:00:00+08:002017-10-26T12:00:00+08:00飞龙tag:feilong.me,2017-10-26:/2017/10/learn-and-practice.html<p>《论语》开篇第一句“学而时习之”,我们小时从课文上学到的解释是“学习并时常复习”,这个解释有其科学依据:</p>
<blockquote>
<p><a href="https://zh.wikipedia.org/wiki/%E9%81%97%E5%BF%98%E6%9B%B2%E7%BA%BF">遗忘曲线</a> —— 记忆过程记忆的保持在时间上是不同的,有短时记忆和长时记忆两种。平时的记忆的过程是:输入的信息在经过人的注意过程的学习后,便成为了人的短时的记忆,再经过进一步强化后成为长时记忆。长时记忆的保持时间有长有短,如果不经过及时的复习,这些记住过的东西就会遗忘,而经过了及时的复习,长时记忆就会继续保持下去。</p>
</blockquote>
<p>明清御用的朱熹注:</p>
<blockquote>
<p>学而又时时习之,则所学者熟,而中心喜说,其进自不能已矣。</p>
</blockquote>
<p>朱熹虽没有直接解释时习,但说时习的效果是“所学者熟”,如书读百遍,书自然就熟了,故其义自见,“时时习”可认为就是指时时复习,朱熹的注和上面的解释一致。若取“复习”之意,则“习”就是学,“复习”也就是学习,只不过是再学习。</p>
<p>钱穆《论语新解》:</p>
<blockquote>
<p>习者,如鸟学飞,数数反复。人之为学,当日复日,年复年,反复不已 …</p></blockquote><p>《论语》开篇第一句“学而时习之”,我们小时从课文上学到的解释是“学习并时常复习”,这个解释有其科学依据:</p>
<blockquote>
<p><a href="https://zh.wikipedia.org/wiki/%E9%81%97%E5%BF%98%E6%9B%B2%E7%BA%BF">遗忘曲线</a> —— 记忆过程记忆的保持在时间上是不同的,有短时记忆和长时记忆两种。平时的记忆的过程是:输入的信息在经过人的注意过程的学习后,便成为了人的短时的记忆,再经过进一步强化后成为长时记忆。长时记忆的保持时间有长有短,如果不经过及时的复习,这些记住过的东西就会遗忘,而经过了及时的复习,长时记忆就会继续保持下去。</p>
</blockquote>
<p>明清御用的朱熹注:</p>
<blockquote>
<p>学而又时时习之,则所学者熟,而中心喜说,其进自不能已矣。</p>
</blockquote>
<p>朱熹虽没有直接解释时习,但说时习的效果是“所学者熟”,如书读百遍,书自然就熟了,故其义自见,“时时习”可认为就是指时时复习,朱熹的注和上面的解释一致。若取“复习”之意,则“习”就是学,“复习”也就是学习,只不过是再学习。</p>
<p>钱穆《论语新解》:</p>
<blockquote>
<p>习者,如鸟学飞,数数反复。人之为学,当日复日,年复年,反复不已,老而无倦。</p>
<p>学能时时反复习之,我心不很欣畅吗?</p>
</blockquote>
<p>“习”,字典上的字面意思本指“鸟不断练飞”,钱穆也做了详细的解释,后面虽用了“时时反复习之”做白话文试译,但白话不够白,没有给出明确的现代文解释,试译中倒是包含了“复习”二字,但其意应更倾向于“反复练习”而不是复习,“习”取了“鸟练飞”的练习之意,“习”不再是学而已是学的一种升级。</p>
<p>无论是读书学习而后不断的复习,还是学弹钢琴等而后不断的练习,我们通常不堪其苦“不亦苦乎”,这点大家都深有体会。以上这两种解释都没办法解释后半句“不亦说乎”,我个人更倾向于将“习”的“练习”之意再升华,取“实践”之意,不靠谱的<a href="https://baike.baidu.com/item/%E5%AD%A6%E8%80%8C%E6%97%B6%E4%B9%A0%E4%B9%8B%EF%BC%8C%E4%B8%8D%E4%BA%A6%E8%AF%B4%E4%B9%8E">百度百科该词条</a>中不知道引用了谁的一段解析倒很到位:</p>
<blockquote>
<p>孔子在“学而时习之,不亦说乎?”这句话中,要表达一种境界的提升,一种行为的变化,恰恰要强调“学”与“习”的差异性!那么,从“学”到“习”的过程,隐含一种从理论到实践的过程;从思想到行为的一种归依。这才是孔子要表达的真正思想内核!在那个还没有形成“理论”与“实践”这一哲学概念的时代,孔子能用什么词汇来表达出自己对这一真理的领悟呢?既要体现出“实践”的含义,又要与学习到的东西有关,除了“习”,他还有别的选择吗?“小鸟反复试飞”这种意境,难道不是他最好的选择吗?可见,在这里,“习”字最佳的解释就是“实践和试验”!</p>
<p>只有学到的能用得上,才能体现学习的价值,在实践中体验成就感;“学以致用”才是孔子提倡学习的根源和出发点。学习者能在实践中实现自己的价值,能不快乐吗?!在实践中验证并丰富对真理的领悟,能不快乐吗?在实践中施展自己的才学、实现自己的理想与抱负,能不快乐吗?这才是孔子“乐”的真谛!</p>
</blockquote>
<p>只有学而假以时日实践之,在学到的理论指导下,学以致用不断的实践并最终取得成功,才能掌握所学,以得到知,完成知与行的合二为一,才能真的“不亦说乎”。</p>
<p>还有一种更不常见的解释,将“习”解释为“习惯”,“学习而假以时日以养成良好的学习习惯”其意虽不靠谱指数最高,但我倒挺喜欢这个解释,我在<a href="/2017/09/09-11-good-habit">成功的习惯</a>中提到我已养成中午固定要阅读学习一段时间的习惯,的确已“不亦乐乎”。</p>
<p>两千多年过去了,孔子说“学而时习之”这句话的时候到底是何意?今人已无从得知,但这不妨碍我们从这几个朴实的字中,按自己的理解汲取到自己想要的营养,学而偶有所得。</p>成功的习惯2017-09-11T22:00:00+08:002017-09-11T22:00:00+08:00飞龙tag:feilong.me,2017-09-11:/2017/09/good-habit.html<p>读书,我除了前面说过的<a href="/2017/09/read-but-forget">过目就忘</a>的坏毛病以外,还有一大毛病是经常虎头蛇尾,不少书读到一半就放弃了。在书本被搁置一段时间后,想再捡起来继续读常常很难成行,因为隔了些时间书本的上下文已生疏,要不得回头翻点前文,要不就干脆得重头再来,因此常常搞得兴趣索然,最终无疾而终,不再提得起兴趣。</p>
<p>我读《资治通鉴》就是最典型的例子,至今为止我读到最远的地方是第二册的西晋初期,但是到商鞅变法至少读过十遍以上;到秦始皇统一六国这段也超过六遍;至汉武帝结束大概也有三遍;越往后读的次数依次递减。但我一直很不甘心,总想着把《资治通鉴》完整的读一遍,今年又不得不重头开始读了起来,为了避免再一次虎头蛇尾,我给自己定了一条小规矩,即无特别的事情耽搁的情况下,每个上班日中午坚持读半个小时至一小时左右的《资治通鉴》,其它时间则随意。这个规矩虽小,好处却很明显:</p>
<ul>
<li>每次中断的时间最长也不会超过几天,继续读时上下文脑中还多少有些印象,接着读不会有多大阻力;</li>
<li>因为无条件的固定的要继续往下读,读书不再那么随性,不会因为汉成帝部分不如汉武帝部分精彩就中途放弃而就此中断。</li>
<li>每次读的差不多半个来小时了,正好睡意绵绵好去午休小憩一下【手动滑稽</li>
</ul>
<p>结果就因为这一个小小的自我约定,渐渐的变成了我的一个阅读习惯,这个习惯养成了以后,其效果出奇的好,也就是利用了每日中午的这些碎片时间,至今我已读完东汉光武帝部分 …</p><p>读书,我除了前面说过的<a href="/2017/09/read-but-forget">过目就忘</a>的坏毛病以外,还有一大毛病是经常虎头蛇尾,不少书读到一半就放弃了。在书本被搁置一段时间后,想再捡起来继续读常常很难成行,因为隔了些时间书本的上下文已生疏,要不得回头翻点前文,要不就干脆得重头再来,因此常常搞得兴趣索然,最终无疾而终,不再提得起兴趣。</p>
<p>我读《资治通鉴》就是最典型的例子,至今为止我读到最远的地方是第二册的西晋初期,但是到商鞅变法至少读过十遍以上;到秦始皇统一六国这段也超过六遍;至汉武帝结束大概也有三遍;越往后读的次数依次递减。但我一直很不甘心,总想着把《资治通鉴》完整的读一遍,今年又不得不重头开始读了起来,为了避免再一次虎头蛇尾,我给自己定了一条小规矩,即无特别的事情耽搁的情况下,每个上班日中午坚持读半个小时至一小时左右的《资治通鉴》,其它时间则随意。这个规矩虽小,好处却很明显:</p>
<ul>
<li>每次中断的时间最长也不会超过几天,继续读时上下文脑中还多少有些印象,接着读不会有多大阻力;</li>
<li>因为无条件的固定的要继续往下读,读书不再那么随性,不会因为汉成帝部分不如汉武帝部分精彩就中途放弃而就此中断。</li>
<li>每次读的差不多半个来小时了,正好睡意绵绵好去午休小憩一下【手动滑稽</li>
</ul>
<p>结果就因为这一个小小的自我约定,渐渐的变成了我的一个阅读习惯,这个习惯养成了以后,其效果出奇的好,也就是利用了每日中午的这些碎片时间,至今我已读完东汉光武帝部分,我也很有信心的说我一定能坚持下去,持续读完四册本《资治通鉴》全书。</p>
<p>借用<a href="https://github.com/astaxie">astaxie</a>用的一句签名“成功的习惯比成功更重要”来说,这个良好习惯的养成比成功读完《资治通鉴》更重要,事实上我已尝到甜头,将类似的约定用到写博客、看美剧、带小孩等事情上,并逐步养成一些习惯,本篇博客就是一个这样的习惯的产物,不时我得逼自己写点啥啊!</p>刘邦的用人艺术:论三杰2017-09-07T18:00:00+08:002017-09-07T18:00:00+08:00飞龙tag:feilong.me,2017-09-07:/2017/09/talent-management.html<p>刘邦以草根(一介亭长)之身短短七年时间就夺取了天下,立下了两汉四百年的宏伟基业,七年时间刘邦参与推翻了秦二世的暴政、垓下一战发动韩信、彭越击败了不可一世的西楚霸王项羽,在与大臣聊天总结自己成功的经验时,刘邦不无自豪的说:</p>
<blockquote>
<p>夫运筹帷幄之中,决胜千里之外,吾不如子房;<br>
填国家,抚百姓,给饷馈,不绝粮道,吾不如萧何;<br>
连百万之众,战必胜,攻必取,吾不如韩信。 </p>
<p>三者皆人杰,吾能用之,此吾所以取天下者也。项羽有一范增而不能用,此所以为我禽也。</p>
</blockquote>
<p>这几句话是刘邦用人艺术的精髓,是用人的至高境界,我的理解它包含以下几层意思:</p>
<ul>
<li>成事核心在于用人,能用好人才者胜,不能用好人才者败;</li>
<li>用人核心在于国士,能用好国士者胜,不能用好国士者败;</li>
<li>老板懂的要广,核心业务多少得懂些,这样方能识人用人;</li>
<li>老板不需要比关键先生更懂核心业务,要有宽广的胸怀能容手下业务能力比自己强;</li>
<li>老板不需要亲力亲为撸起袖子自己干,事实上刘邦自己带兵跟项羽干架总输的很惨;</li>
<li>老板要能充分认识到自己能力的不足,放心大胆的放权将业务交给最擅长的人去干。</li>
</ul>
<p><a href="http://36kr.com/p/5091545.html">朱立南谈CEO的角色意识</a>的文章中关于识人用人有类似的观点:</p>
<blockquote>
<p>创业早期,CEO几乎各方面都是最行的,市场也好、销售也好 …</p></blockquote><p>刘邦以草根(一介亭长)之身短短七年时间就夺取了天下,立下了两汉四百年的宏伟基业,七年时间刘邦参与推翻了秦二世的暴政、垓下一战发动韩信、彭越击败了不可一世的西楚霸王项羽,在与大臣聊天总结自己成功的经验时,刘邦不无自豪的说:</p>
<blockquote>
<p>夫运筹帷幄之中,决胜千里之外,吾不如子房;<br>
填国家,抚百姓,给饷馈,不绝粮道,吾不如萧何;<br>
连百万之众,战必胜,攻必取,吾不如韩信。 </p>
<p>三者皆人杰,吾能用之,此吾所以取天下者也。项羽有一范增而不能用,此所以为我禽也。</p>
</blockquote>
<p>这几句话是刘邦用人艺术的精髓,是用人的至高境界,我的理解它包含以下几层意思:</p>
<ul>
<li>成事核心在于用人,能用好人才者胜,不能用好人才者败;</li>
<li>用人核心在于国士,能用好国士者胜,不能用好国士者败;</li>
<li>老板懂的要广,核心业务多少得懂些,这样方能识人用人;</li>
<li>老板不需要比关键先生更懂核心业务,要有宽广的胸怀能容手下业务能力比自己强;</li>
<li>老板不需要亲力亲为撸起袖子自己干,事实上刘邦自己带兵跟项羽干架总输的很惨;</li>
<li>老板要能充分认识到自己能力的不足,放心大胆的放权将业务交给最擅长的人去干。</li>
</ul>
<p><a href="http://36kr.com/p/5091545.html">朱立南谈CEO的角色意识</a>的文章中关于识人用人有类似的观点:</p>
<blockquote>
<p>创业早期,CEO几乎各方面都是最行的,市场也好、销售也好、甚至产品也好。当企业规模做大以后,你必须得意识到,如果这个企业价值链所有的环节你都是最行的,就会出现两个问题:</p>
<ul>
<li>
<p>第一、你可能是公司最行的,但不是业界,也不是市场上最好的;</p>
</li>
<li>
<p>第二、公司没有一个真正好的体系来支持,让你能腾出精力考虑对未来发展最重要的事情,比如说战略,比如说组织。</p>
</li>
</ul>
<p>所以要刻意的让自己放弃掉一些其实你比较擅长的事情,回归到一个CEO应该做的一些工作上,我觉得这也是自我认知和自我调整的一个过程。这里面也有一个尴尬的地方,可能你会有一个阶段,当你找到人或者内部培养人,在这方面不如你,你很忍不住要自己动手。比如说一个市场活动,你请他做了,他把预案告诉你,你一看,实在跟你的水平差距很大,恨不得我来做一份更好的。这个阶段你怎么抑制住自己的冲动,去帮助这个人能够成为这个行业里面最好的人,或者找更好的人替代他。</p>
<p>总之,CEO有的时候要非常注意的就是,要抑制住自己所谓的长项,回归到自己做事情的本质上去,在相关领域里面找到最合适的人形成一股合力,促进企业整体能力的提升。这一点特别重要。</p>
</blockquote>
<p>刘邦的用人艺术还有很多可以去讲,今天先挑最具代表的一个,以后可以再展开说说。</p>读书过目就忘,怎么办?2017-09-07T14:00:00+08:002017-09-07T14:00:00+08:00飞龙tag:feilong.me,2017-09-07:/2017/09/read-but-forget.html<p>两年前一位朋友给我推荐了知乎日报的“瞎扯 - 如何正确的吐槽”,这个瞎扯的画风是这样的:</p>
<p><img alt="知乎日报-瞎扯" src="/static/2017/09-07-zhihu-humor.jpg"></p>
<p>从那以后我每天都会打开知乎日报看日报的瞎扯,瞎扯里面的知乎抖机灵党很多,看时每每会会心一笑,然而要我说今天看过的瞎扯讲了啥,我已一点印象都没有了,更不用说往期的了。除了看瞎扯有此困惑以外,平时阅读书籍亦是如此,经常重翻一些书的时候感觉就像从来没有读过一样。一方面我不得不佩服我自己的记忆力,羡煞有过目不忘能力的人;另一方面我也总在琢磨是不是借助一些书摘工具来辅助自己的记忆,找了一圈APP总没有找到适合我用的,难道只能我自己开发一个才能满足我个人的需求吗?或许可以业余折腾一个这样的微信小程序试试水,毕竟要"Scratch your own itch"嘛!</p>
<p>虽然过目就忘,但我很喜欢看瞎扯、很喜欢读书,每天都用大量的时间来阅读,在每次阅读的过程中攫取了一些信息或知识,享受了阅读的快乐,至于能记住多少是多少了,最后,我用这位朋友安慰过我的一句话再安慰下我自己:</p>
<blockquote>
<p>你读过的书,经历过的事,等时间长了,那些细枝末节你都忘了,剩下来的,就成了你的素质。</p>
</blockquote>
<p>过目就忘,忘了就让它成为我的素质吧 :)</p><p>两年前一位朋友给我推荐了知乎日报的“瞎扯 - 如何正确的吐槽”,这个瞎扯的画风是这样的:</p>
<p><img alt="知乎日报-瞎扯" src="/static/2017/09-07-zhihu-humor.jpg"></p>
<p>从那以后我每天都会打开知乎日报看日报的瞎扯,瞎扯里面的知乎抖机灵党很多,看时每每会会心一笑,然而要我说今天看过的瞎扯讲了啥,我已一点印象都没有了,更不用说往期的了。除了看瞎扯有此困惑以外,平时阅读书籍亦是如此,经常重翻一些书的时候感觉就像从来没有读过一样。一方面我不得不佩服我自己的记忆力,羡煞有过目不忘能力的人;另一方面我也总在琢磨是不是借助一些书摘工具来辅助自己的记忆,找了一圈APP总没有找到适合我用的,难道只能我自己开发一个才能满足我个人的需求吗?或许可以业余折腾一个这样的微信小程序试试水,毕竟要"Scratch your own itch"嘛!</p>
<p>虽然过目就忘,但我很喜欢看瞎扯、很喜欢读书,每天都用大量的时间来阅读,在每次阅读的过程中攫取了一些信息或知识,享受了阅读的快乐,至于能记住多少是多少了,最后,我用这位朋友安慰过我的一句话再安慰下我自己:</p>
<blockquote>
<p>你读过的书,经历过的事,等时间长了,那些细枝末节你都忘了,剩下来的,就成了你的素质。</p>
</blockquote>
<p>过目就忘,忘了就让它成为我的素质吧 :)</p>玩索而有得2017-08-15T17:00:00+08:002017-08-15T17:00:00+08:00飞龙tag:feilong.me,2017-08-15:/2017/08/play-then-gain.html<p>“玩索而有得”这句话我初见于《易经杂说》:</p>
<blockquote>
<p>我们现在开始研究《易经》,有一个法则要把握住,这个法则就在手边这本书上,孔子研究了《易经》以后说出来的。他这句话很妙,他说:“玩索而有得。”学《易经》最好用打麻将的方式来学它,如果把八卦刻在麻将牌上,摸起来就趣味无穷了。孔子教我们念别的书,都是要持严肃的态度,唯有教我们学《易》,要“玩索而有得”,要天天玩它。</p>
</blockquote>
<p>“玩索而有得,要天天玩它”,马化腾对此似亦深有体会,他在香港大学的活动上分享<a href="http://tech.qq.com/a/20150601/014134.htm">产品经理最重要的能力是把自己变傻瓜</a>中说:</p>
<blockquote>
<p>我是软件工程师中的产品经理,最终要决定产品的走向、对用户体验的把握。所以我会花大量时间用这个产品,尤其是最核心的微信、QQ、Email。<br>
没有(诀窍),大量用,不断地用,尽量找沟通的场景,慢慢地找到感觉。</p>
</blockquote>
<p>两年前我前后花了一个月左右时间开发,做过一款实验性的产品<a href="http://pianjian.me">偏见APP</a>,“偏见”开发周期短功能并不完整,只能算是个半成品 …</p><p>“玩索而有得”这句话我初见于《易经杂说》:</p>
<blockquote>
<p>我们现在开始研究《易经》,有一个法则要把握住,这个法则就在手边这本书上,孔子研究了《易经》以后说出来的。他这句话很妙,他说:“玩索而有得。”学《易经》最好用打麻将的方式来学它,如果把八卦刻在麻将牌上,摸起来就趣味无穷了。孔子教我们念别的书,都是要持严肃的态度,唯有教我们学《易》,要“玩索而有得”,要天天玩它。</p>
</blockquote>
<p>“玩索而有得,要天天玩它”,马化腾对此似亦深有体会,他在香港大学的活动上分享<a href="http://tech.qq.com/a/20150601/014134.htm">产品经理最重要的能力是把自己变傻瓜</a>中说:</p>
<blockquote>
<p>我是软件工程师中的产品经理,最终要决定产品的走向、对用户体验的把握。所以我会花大量时间用这个产品,尤其是最核心的微信、QQ、Email。<br>
没有(诀窍),大量用,不断地用,尽量找沟通的场景,慢慢地找到感觉。</p>
</blockquote>
<p>两年前我前后花了一个月左右时间开发,做过一款实验性的产品<a href="http://pianjian.me">偏见APP</a>,“偏见”开发周期短功能并不完整,只能算是个半成品,上线后修了部分bug,到2016年2月发布1.0.5版本之后至今就没有再发过新版本,客户端遗留的bug比较多,尤其是安卓客户端(偏偏安卓用户占绝大多数)。有趣的是,“偏见”虽然一年半没有更新版本,魅族应用市场却在近期的一次简约主题的首页推荐中推荐了“偏见”,“偏见”也因此涌来了一波新用户,加之“偏见”有幸一直有一小撮用户在使用,且沉湎其中乐此不疲,因此在这波用户的“逼迫”下,我不得不重新提起“偏见”版本的更新,来修掉一些严重影响用户体验的bug。</p>
<p>我平时用iPhone手机,安卓版“偏见”发布之后再很少使用,安卓版本的bug主要来源于之前用户的反馈,汇总了有十来条高优先级问题,这次请人一并帮我修了,修完后我昨天开始测试问题修复情况,又开始玩"偏见"安卓版,这一玩我大吃了一惊:</p>
<ul>
<li>惊的是安卓版本居然这么难用</li>
<li>惊的是有那么多细节未做到位</li>
<li>惊的是用户对偏见不足的包容</li>
<li>惊的是忠粉对偏见的不离不弃</li>
</ul>
<p>前两条玩了安卓版才意识到,后两条日常用iOS版时虽已有所体会,用了安卓基于前两条才有了更深刻的感触。如最近新加的一个“三行文字自动转图”的彩蛋,字多点的图在安卓下字体显得太小根本就看不清楚。真是不玩不知道,一玩吓一跳,这么挫的"偏见",仍不失用户的喜爱,更显的“偏见”有可贵的点在,若再不多玩、多体会、多改进,诚不愧于吾心么。改进产品,只有大量用,不断地用,慢慢地自能找到产品的感觉,并没有别的诀窍可循了。</p>
<p>玩索而有得,真是做产品的不二法门。</p>厚积而薄发2017-08-11T17:00:00+08:002017-08-11T17:00:00+08:00飞龙tag:feilong.me,2017-08-11:/2017/08/all-about-long-term.html<p><img alt="厚积薄发" src="/static/2017/08-11-houjibofa.jpg"></p>
<p>厚积薄发四个“大”字,在我看来并不是一样大,发是最终要能达到的果,积是因,厚积而薄发整体是一个上升的曲线,在正确的方向上有了长时间的积累和沉淀后,发将是水到渠成的事,其上升之势不可阻挡。</p>
<p><img alt="上海中心" src="/static/2017/08-11-towers.jpg"></p>
<blockquote>
<p>《易经》升卦:君子以顺德,积小以高大。<br>
《道德经》:合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。 </p>
</blockquote>
<p>上海三大楼正是一砖一瓦一点点砌起来的,有意思的是:</p>
<ul>
<li>上海中心的外形是螺旋上升式的,“升”通常不是直升而是起起伏伏的螺旋式上升。</li>
<li>图中还隐藏了最重要的一部分,地基:<blockquote>
<p>上海浦东处在一个冲积层,上海中心的建造地点位于一个河流三角洲,土质松软,含有大量粘土。在竖起钢梁前,工程师打了980个基桩,深度达到282英尺(约合86米),而后浇筑215万立方英尺(约合60881立方米)混凝土进行加固,形成一个20英尺(约合6米)厚的基础底板。</p>
</blockquote>
</li>
</ul>
<p>只有厚积夯实了地基,才有600米高楼拔地而起。</p>
<p>厚积薄发来源于古老的中国传统文化,精益创业则近年从硅谷传来,被互联网行业创业者奉为圭臬。厚积薄发和精益创业看似矛盾、实则统一,借用毛泽东在 …</p><p><img alt="厚积薄发" src="/static/2017/08-11-houjibofa.jpg"></p>
<p>厚积薄发四个“大”字,在我看来并不是一样大,发是最终要能达到的果,积是因,厚积而薄发整体是一个上升的曲线,在正确的方向上有了长时间的积累和沉淀后,发将是水到渠成的事,其上升之势不可阻挡。</p>
<p><img alt="上海中心" src="/static/2017/08-11-towers.jpg"></p>
<blockquote>
<p>《易经》升卦:君子以顺德,积小以高大。<br>
《道德经》:合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。 </p>
</blockquote>
<p>上海三大楼正是一砖一瓦一点点砌起来的,有意思的是:</p>
<ul>
<li>上海中心的外形是螺旋上升式的,“升”通常不是直升而是起起伏伏的螺旋式上升。</li>
<li>图中还隐藏了最重要的一部分,地基:<blockquote>
<p>上海浦东处在一个冲积层,上海中心的建造地点位于一个河流三角洲,土质松软,含有大量粘土。在竖起钢梁前,工程师打了980个基桩,深度达到282英尺(约合86米),而后浇筑215万立方英尺(约合60881立方米)混凝土进行加固,形成一个20英尺(约合6米)厚的基础底板。</p>
</blockquote>
</li>
</ul>
<p>只有厚积夯实了地基,才有600米高楼拔地而起。</p>
<p>厚积薄发来源于古老的中国传统文化,精益创业则近年从硅谷传来,被互联网行业创业者奉为圭臬。厚积薄发和精益创业看似矛盾、实则统一,借用毛泽东在《论持久战》中反复论述的两句话“战略上的内线的持久的防御战,战役战斗上的外线的速决的进攻战”来做类比,战略对战役战斗、内线对外线、持久对速决、防御对进攻均是相对的词汇,但这两句话正是《论持久战》精髓之所在,是持久战的一体两面、相辅相成,就好比一只手掌的正反面,厚积薄发和精益创业之间的关系亦是如此:</p>
<ul>
<li>战略上:以慢打快,厚积薄发</li>
<li>战术上:小步快跑,精益开发</li>
<li>心态上:耐得住寂寞,经得起诱惑</li>
</ul>
<p>在这三点上,Amazon是我们学习的榜样,早在1997年贝索斯给股东的信中就说:</p>
<blockquote>
<p>“It's All About the Long Term” </p>
<p>Because of our emphasis on the long term, we may make decisions and weigh tradeoffs differently than some companies.</p>
</blockquote>
<p>贝索斯也一直在践行这封信中所持的Long Term的理念,鲜为人知的是2002年Amazon就布局了云计算Amazon Web Services(简称AWS),但直到2015年Amazon才首次披露AWS的财报,之后的Amazon股价一路飙升,2015年的股价几乎翻了一倍。十多年来,AWS从相对单一的EC2和S3到无所不包的产品线、从无人知晓到路人皆知,立足未来、小步快跑一路走来,云计算本会是Google、Microsoft、IBM等公司的强势领域,但成为行业翘楚的却是当年靠卖书起家的Amazon,不得不说AWS是一个奇迹、Amazon是一个奇迹。Amazon历二十余年的积累,虽长期亏损但一直坚持走Long Term路线,布局深远、厚积而薄发,股价今年业已突破1000美金,展现出强劲的持续上升的势头。</p>
<p><img alt="亚马逊股价" src="/static/2017/08-11-amazon-stock.jpg"></p>
<p>以Amazon为学习标杆,谨记“余生很长,何必惊慌”,少挖新坑、多挖深坑,找准一个方向坚持下去,夯牢基础,终有所成。</p>三思而后行2017-06-19T17:00:00+08:002017-06-19T17:00:00+08:00飞龙tag:feilong.me,2017-06-19:/2017/06/think-twice.html<p>昨天做了一件当时认为很明智事后发现很愚蠢的事情,问题出就出在对事欠考虑,造成了几乎无法挽回的损失,真是快被自己蠢哭了。</p>
<p>事情是这样的,昨天下午我清理最近搬家后尚未处理完的一些箱子,其中一个是以前的光盘盒子,包括一堆很老的游戏盘、电影电视盘、工具盘、自己刻录的盘和老婆孩子的一些活动刻录盘。因为时间久远,除了活动盘和有点纪念价值的游戏光盘可留个念想外,大部分光盘已经失去其价值了,本着为家里多腾空间不留垃圾的原则决定清掉这些无用光盘。</p>
<p>游戏盘、电影电视盘、工具盘通常会有光盘纸盒并且光盘上印有光盘内容信息,都比较好分辨,自己刻录的盘就比较尴尬,说明光盘内容的标记信息现已或有或无,一些盘从盘面看已无从判断里面到底刻了啥。其中就有那么两张这样的盘,我已搞不清到底是个啥,想想没啥价值还是扔了算了,因为是刻录的盘,担心盘内刻有家人照片或活动视频被人捡了泄露隐私,这时候我不知道怎么脑抽了一下,把这些盘狠狠的在地面上摩擦摩擦再摩擦刻意把盘划花了,光盘与地面摩擦的声音是那么的悦耳,我陶醉于自己的小聪明中。这里有个小背景,家里只有一台很老的极少使用的PC机有光驱,其它全是没光驱的苹果设备,因为搬家不久尚未将这台PC装起来用,所以在划盘之前懒了一步用电脑打开这两张盘看看到底里面有啥,就此铸成大错。</p>
<p>在整理完光盘后不久,我老婆看到我整理了光盘突然想起一事,问我是否还有早年QQ聊天时的聊天记录,这必须有啊,我当年刻在了一张光盘上……</p>
<p>很不幸,这张盘正是那两张被我摩擦过的盘之一,为了找到这张光盘我重新查看了留下的和已丢进垃圾箱的所有光盘,被迫装起了上面提到的那台PC来检查所有可疑的盘。接下来,一直折腾到第二天早上5点,我花了一个晚上的时间来研究和尝试Google到的各种恢复有划痕光盘数据的办法,最终通过牙膏打磨光盘和CD …</p><p>昨天做了一件当时认为很明智事后发现很愚蠢的事情,问题出就出在对事欠考虑,造成了几乎无法挽回的损失,真是快被自己蠢哭了。</p>
<p>事情是这样的,昨天下午我清理最近搬家后尚未处理完的一些箱子,其中一个是以前的光盘盒子,包括一堆很老的游戏盘、电影电视盘、工具盘、自己刻录的盘和老婆孩子的一些活动刻录盘。因为时间久远,除了活动盘和有点纪念价值的游戏光盘可留个念想外,大部分光盘已经失去其价值了,本着为家里多腾空间不留垃圾的原则决定清掉这些无用光盘。</p>
<p>游戏盘、电影电视盘、工具盘通常会有光盘纸盒并且光盘上印有光盘内容信息,都比较好分辨,自己刻录的盘就比较尴尬,说明光盘内容的标记信息现已或有或无,一些盘从盘面看已无从判断里面到底刻了啥。其中就有那么两张这样的盘,我已搞不清到底是个啥,想想没啥价值还是扔了算了,因为是刻录的盘,担心盘内刻有家人照片或活动视频被人捡了泄露隐私,这时候我不知道怎么脑抽了一下,把这些盘狠狠的在地面上摩擦摩擦再摩擦刻意把盘划花了,光盘与地面摩擦的声音是那么的悦耳,我陶醉于自己的小聪明中。这里有个小背景,家里只有一台很老的极少使用的PC机有光驱,其它全是没光驱的苹果设备,因为搬家不久尚未将这台PC装起来用,所以在划盘之前懒了一步用电脑打开这两张盘看看到底里面有啥,就此铸成大错。</p>
<p>在整理完光盘后不久,我老婆看到我整理了光盘突然想起一事,问我是否还有早年QQ聊天时的聊天记录,这必须有啊,我当年刻在了一张光盘上……</p>
<p>很不幸,这张盘正是那两张被我摩擦过的盘之一,为了找到这张光盘我重新查看了留下的和已丢进垃圾箱的所有光盘,被迫装起了上面提到的那台PC来检查所有可疑的盘。接下来,一直折腾到第二天早上5点,我花了一个晚上的时间来研究和尝试Google到的各种恢复有划痕光盘数据的办法,最终通过牙膏打磨光盘和CD Recovery软件,恢复了盘中我最想要的聊天记录文件的大部分,不幸中的万幸是幸好当时保存的是多个txt文件。</p>
<p>造成此次悲剧的是,做破坏性的划花光盘之前我未三思而后行,一秒钟的过错,近十个小时的补救,尚不能挽回全部损失。此事虽小,教训不可谓不深刻,戒之戒之戒之!!!</p>关于挽留提离职的人员2017-05-11T17:00:00+08:002017-05-11T17:00:00+08:00飞龙tag:feilong.me,2017-05-11:/2017/05/about-resignation.html<p>V站上<a href="https://www.v2ex.com/t/360243">关于离职被挽留,求大大们给点建议</a>我的回答概括如下:</p>
<ol>
<li>
<p>公司为挽留你做较大幅度的薪资调整操作难度大,不是说公司付不起这增加的部分工资,而是公司不好处理后面其他人员提离职。</p>
</li>
<li>
<p>新招人有时间成本,挽留是更多的是因为公司要尽量降低人员流失带来的风险,要搞清楚挽留你的关键原因?</p>
</li>
<li>
<p>通常一个人提出了离职后,被公司增加薪酬待遇挽留下来的都不长久。提离职就可以涨薪你让辛勤工作的人怎么想,后面自己不提离职就薪资不再长了自己又怎么想,即使留下来了后面也免不了再提离职、再调薪、再提离职、终于公司无法满足你的需求而离职的怪圈。 </p>
</li>
<li>
<p>一个公司在员工提离职时才想到加薪挽留,一定程度上是公司无能的表现。</p>
</li>
</ol>
<p>搜了下知乎上的同类问题,发现Ivony在<a href="https://www.zhihu.com/question/21234709">提离职被老板加薪挽留,该怎么办?</a>中的回答很有借鉴意义:</p>
<ul>
<li>提出离职之前,应当先提出加薪申请</li>
<li>提出离职之时,一定要果决,理由必须是私人原因</li>
<li>没有什么公司是不操蛋的,你去哪个公司都有操蛋的事情,多少、程度和方面的不同而已</li>
<li>是去是留,选择前慎重,选择后珍重</li>
</ul>
<p>余世维在《成功经理人》讲座里曾提到他对待员工提离职的一套做法,大意是只要主动提出离职的一律现场签字一个留,他的做法或许有些偏激,但从公司经营的角度讲,未尝不是办法的办法,个人比较赞同他这一套,但是要能贯彻执行这一套需要公司能够做到:</p>
<ul>
<li>定期&尽早地发现并提拔优秀人才</li>
<li>提前做好不可或缺的关键岗位的后备人员储备</li>
<li>应提前灌输 …</li></ul><p>V站上<a href="https://www.v2ex.com/t/360243">关于离职被挽留,求大大们给点建议</a>我的回答概括如下:</p>
<ol>
<li>
<p>公司为挽留你做较大幅度的薪资调整操作难度大,不是说公司付不起这增加的部分工资,而是公司不好处理后面其他人员提离职。</p>
</li>
<li>
<p>新招人有时间成本,挽留是更多的是因为公司要尽量降低人员流失带来的风险,要搞清楚挽留你的关键原因?</p>
</li>
<li>
<p>通常一个人提出了离职后,被公司增加薪酬待遇挽留下来的都不长久。提离职就可以涨薪你让辛勤工作的人怎么想,后面自己不提离职就薪资不再长了自己又怎么想,即使留下来了后面也免不了再提离职、再调薪、再提离职、终于公司无法满足你的需求而离职的怪圈。 </p>
</li>
<li>
<p>一个公司在员工提离职时才想到加薪挽留,一定程度上是公司无能的表现。</p>
</li>
</ol>
<p>搜了下知乎上的同类问题,发现Ivony在<a href="https://www.zhihu.com/question/21234709">提离职被老板加薪挽留,该怎么办?</a>中的回答很有借鉴意义:</p>
<ul>
<li>提出离职之前,应当先提出加薪申请</li>
<li>提出离职之时,一定要果决,理由必须是私人原因</li>
<li>没有什么公司是不操蛋的,你去哪个公司都有操蛋的事情,多少、程度和方面的不同而已</li>
<li>是去是留,选择前慎重,选择后珍重</li>
</ul>
<p>余世维在《成功经理人》讲座里曾提到他对待员工提离职的一套做法,大意是只要主动提出离职的一律现场签字一个留,他的做法或许有些偏激,但从公司经营的角度讲,未尝不是办法的办法,个人比较赞同他这一套,但是要能贯彻执行这一套需要公司能够做到:</p>
<ul>
<li>定期&尽早地发现并提拔优秀人才</li>
<li>提前做好不可或缺的关键岗位的后备人员储备</li>
<li>应提前灌输“提出离职一律不留”到员工认知中</li>
</ul>
<p>但要做到以上三点很不容易,重要人员提离职绝对是个棘手的问题,老板也不好当啊!</p>弃坑《率土之滨》2017-04-28T11:00:00+08:002017-04-28T11:00:00+08:00飞龙tag:feilong.me,2017-04-28:/2017/04/afk-stzb.html<p>4月12-16日蒙公司福利我去了趟巴厘岛旅游,巴厘岛是著名的旅游岛,海天一色风光旖旎,有图为证:</p>
<p><img alt="bali" src="/static/2017/04-28-bali-1.jpeg">
<img alt="bali" src="/static/2017/04-28-bali-2.jpeg">
<img alt="bali" src="/static/2017/04-28-bali-3.jpeg"> </p>
<p>巴里岛的景色太美,以致于我无暇去玩《率土之滨》,<a href="http://stzb.163.com/">《率土之滨》</a>是网易出品的一款三国题材沙盘战略手游,率土玩法独特、制作精良、既氪又肝。出于职业习惯我经常和同事聊率土的开发实现方案,个人认为开发的挑战是很大的,这款游戏的制作成本绝对不低。率土面世一年多到目前为止已开了近400个游戏服,在App Store畅销榜上的排名也一直比较靠前,市场反响还是不错的。</p>
<p>我上一次肝一款游戏还是2013年,当时玩了近一年的《四国战记》,四国也很肝,但后来我自己开发了全自动的<a href="/2013/08/siguozhanji-boss-fight-robot">四国外挂</a>缓解了肝的问题。率土虽好,可是太肝,每个赛季初的发展时期和州战时期特别特别特别耗时间,少玩一会你的发展就慢一拍,影响到整个赛季的战局。和张小龙提倡的用完即走或《王者荣耀》的10分钟撸一局不同,率土在游戏机制上想尽办法捆绑用户的时间,这也是市面上大部分游戏的套路。因为率土太肝,所以你上下班路上得肝、吃饭时得肝、带娃的时候抽空得肝、半夜偶然醒来得肝,近一年我有大把的业余时间被率土吞噬,因为太占时间屡次想中途弃坑而未果。这次刚到巴厘岛在旅游大巴上我就玩起了率土,当窗外巴厘岛令人窒息的美扑面而来的时候,突然觉得不能因为游戏的肝而错过身边的美(早有朋友提醒过我“不要老低头看手机,美就在你身边”),果断暂时删了率土 …</p><p>4月12-16日蒙公司福利我去了趟巴厘岛旅游,巴厘岛是著名的旅游岛,海天一色风光旖旎,有图为证:</p>
<p><img alt="bali" src="/static/2017/04-28-bali-1.jpeg">
<img alt="bali" src="/static/2017/04-28-bali-2.jpeg">
<img alt="bali" src="/static/2017/04-28-bali-3.jpeg"> </p>
<p>巴里岛的景色太美,以致于我无暇去玩《率土之滨》,<a href="http://stzb.163.com/">《率土之滨》</a>是网易出品的一款三国题材沙盘战略手游,率土玩法独特、制作精良、既氪又肝。出于职业习惯我经常和同事聊率土的开发实现方案,个人认为开发的挑战是很大的,这款游戏的制作成本绝对不低。率土面世一年多到目前为止已开了近400个游戏服,在App Store畅销榜上的排名也一直比较靠前,市场反响还是不错的。</p>
<p>我上一次肝一款游戏还是2013年,当时玩了近一年的《四国战记》,四国也很肝,但后来我自己开发了全自动的<a href="/2013/08/siguozhanji-boss-fight-robot">四国外挂</a>缓解了肝的问题。率土虽好,可是太肝,每个赛季初的发展时期和州战时期特别特别特别耗时间,少玩一会你的发展就慢一拍,影响到整个赛季的战局。和张小龙提倡的用完即走或《王者荣耀》的10分钟撸一局不同,率土在游戏机制上想尽办法捆绑用户的时间,这也是市面上大部分游戏的套路。因为率土太肝,所以你上下班路上得肝、吃饭时得肝、带娃的时候抽空得肝、半夜偶然醒来得肝,近一年我有大把的业余时间被率土吞噬,因为太占时间屡次想中途弃坑而未果。这次刚到巴厘岛在旅游大巴上我就玩起了率土,当窗外巴厘岛令人窒息的美扑面而来的时候,突然觉得不能因为游戏的肝而错过身边的美(早有朋友提醒过我“不要老低头看手机,美就在你身边”),果断暂时删了率土,没了率土这趟旅行让我尽享了巴厘岛的美。回国再看率土群里的讨论,五天的州战盟里已发生天翻地覆的变化,我的号已跟不上节奏,我上去再玩的一点动力都没有了。从在巴厘岛上删掉率土至今,我没有再碰一次率土,从暂时不玩变成正式弃坑,没有率土的日子,上下班路上我有更多的时间来读书看电影、下班有更多的时间陪孩子、晚上有更多的时间休息,少了率土,多了许多人生乐趣。</p>
<p>游戏的肝是把双刃剑,通过掠取用户时间是可以赚取更多的付费营收,但控制不合理游戏太肝太累玩家提早弃坑就变成了杀鸡取卵,10分钟一局的《王者荣耀》已王者无敌,老子说的“夫唯不争,故天下莫能与之争”或许是最好的注解。</p>
<p>远离伤肝的游戏,珍惜身边的美丽!</p>开源,何乐而不为!2017-03-27T16:50:00+08:002017-03-27T16:50:00+08:00飞龙tag:feilong.me,2017-03-27:/2017/03/open-source-to-github.html<p>@nito在v2ex上怯生生的问<a href="https://www.v2ex.com/t/350259">github 没人 star,能写进简历吗?</a>,我在帖子里的回答是:</p>
<blockquote>
<p>放,为什么不放?</p>
<ol>
<li>如 @est 所说已经能比下去不少人了; </li>
<li>自己准备好放上去的项目肯定是自己认为较好的代码才放上去的,代表了自己的真实水平,能看上你的人能通过项目代码早点看上你,看不上你代码的则表示不认可你当前的能力,如果没有看到开源的代码,哪怕你侥幸面试过关了,能力达不到要求以后工作也不一定能顺利,所以放于人于己也都是件好事。 </li>
<li>虽然当前没有 star ,不表示后面不会有 star ; </li>
<li>虽然现在还是 demo 级,不表示以后一直是 demo ,很多好项目甚至公司就是从一个 demo 开始的。</li>
</ol>
</blockquote>
<p>我个人的招聘习惯,只要看到带有github地址的简历,初始印象分马上就上去了,github是一个很好的加分项,我一定会点进去看看项目star、commit情况,并翻翻代码实现,通过代码初步判断候选者的编程能力和编程习惯。面试时我也经常会问一些候选者:</p>
<ul>
<li>是否经常使用github?</li>
<li>是否有一些代码可以开源?</li>
<li>为什么没有开源?</li>
</ul>
<p>以此来判断候选者:</p>
<ul>
<li>是否经常通过开源社区来解决实际问题?</li>
<li>是否有好的对代码的归纳提炼能力?</li>
<li>是否有好的沟通协作能力?</li>
<li>是否既会索取也懂得奉献?</li>
<li>是否足够有自信?</li>
</ul>
<p>程序员经常会有如下的体会 …</p><p>@nito在v2ex上怯生生的问<a href="https://www.v2ex.com/t/350259">github 没人 star,能写进简历吗?</a>,我在帖子里的回答是:</p>
<blockquote>
<p>放,为什么不放?</p>
<ol>
<li>如 @est 所说已经能比下去不少人了; </li>
<li>自己准备好放上去的项目肯定是自己认为较好的代码才放上去的,代表了自己的真实水平,能看上你的人能通过项目代码早点看上你,看不上你代码的则表示不认可你当前的能力,如果没有看到开源的代码,哪怕你侥幸面试过关了,能力达不到要求以后工作也不一定能顺利,所以放于人于己也都是件好事。 </li>
<li>虽然当前没有 star ,不表示后面不会有 star ; </li>
<li>虽然现在还是 demo 级,不表示以后一直是 demo ,很多好项目甚至公司就是从一个 demo 开始的。</li>
</ol>
</blockquote>
<p>我个人的招聘习惯,只要看到带有github地址的简历,初始印象分马上就上去了,github是一个很好的加分项,我一定会点进去看看项目star、commit情况,并翻翻代码实现,通过代码初步判断候选者的编程能力和编程习惯。面试时我也经常会问一些候选者:</p>
<ul>
<li>是否经常使用github?</li>
<li>是否有一些代码可以开源?</li>
<li>为什么没有开源?</li>
</ul>
<p>以此来判断候选者:</p>
<ul>
<li>是否经常通过开源社区来解决实际问题?</li>
<li>是否有好的对代码的归纳提炼能力?</li>
<li>是否有好的沟通协作能力?</li>
<li>是否既会索取也懂得奉献?</li>
<li>是否足够有自信?</li>
</ul>
<p>程序员经常会有如下的体会:</p>
<blockquote>
<p>之前自己写的XXX代码太烂了,简直就像一坨屎...</p>
</blockquote>
<p>这是一件好事,认识到老代码的不足,正说明自身能力已提升。代码写的烂不要紧,要紧的是不持续优化改进。将自己的非商业代码大胆的开源出来,接受群众的检验和社区的驱动,是提升自身能力的绝佳机会。</p>
<p>2013年我刚接触到<a href="https://github.com/nsqio/nsq">NSQ</a>时,发现NSQ官方的Python驱动<a href="https://github.com/nsqio/pynsq">pynsq</a>还没有发消息的接口,所以提了一个feature需求<a href="https://github.com/nsqio/pynsq/pull/11">add Writer API</a>,NSQ主要作者之一<a href="https://github.com/mreiferson">mreiferson</a>建议我暂时用HTTP的接口,既然还没有而我又有需求那我就自己尝试实现一个吧,经过几天的努力我开发了一版提交了PR <a href="https://github.com/nsqio/pynsq/pull/25">Add async Writer to support pub&mpub</a>,可以说我最早提交的一版代码是很粗糙的,但这个代码让我有了和世界级高手对话的机会,经过mreiferson的指点我不断优化和完善了代码,最终,由我实现的Writer代码merge进了pynsq的master。</p>
<p>Go web开发框架<a href="https://github.com/astaxie/beego">beego</a>最初是谢大@astaxie学习Go语言时仿Tornado实现的一个玩具项目,开源到了github上,早期被很多人喷设计不佳、代码不优雅、谢大个人傲慢等,有兴趣的v2ex上可以搜到老的吐槽的帖子。当时代码丑不丑?据我所知多少是有点丑的,但是多年过去了,beego经过谢大持续不断的优化和完善,已经成为github上的明星项目,star数超过了一万,被包括华为、360等很多一线大厂广泛地采用,谢大个人也成为国内Go开发界的风云人物,而喷他的那些人谁还记得?</p>
<p>以上两个案例一个是我自己、一个是我身边好友的亲身经历,通过开源为社区做出了贡献的同时,自身能力、影响力也不知不觉的得到了提升。</p>
<p><strong>开源,何乐而不为!</strong></p>Less is more2017-03-20T12:50:00+08:002017-03-20T12:50:00+08:00飞龙tag:feilong.me,2017-03-20:/2017/03/less-is-more.html<p>如果老子会说英语,那么“Less is more”一定出于其口,老子在《道德经》中早就有云“曲则全,枉则直,洼则盈,敝则新,少则得,多则惑”,真乃字字珠玑。</p>
<p>相比于上一个时代的全键盘手机,iPhone只有一个Home键是诠释“Less is more”最好的一个例子:
<img alt="blackberry" src="/static/2017/03-20-blackberry.jpg">
<img alt="iphone" src="/static/2017/03-20-iphone.png"> </p>
<p>Golang的发明人之一Rob Pike则更进一步说<a href="https://commandcenter.blogspot.jp/2012/06/less-is-exponentially-more.html">“Less is exponentially more”</a>并拿Go举例说:</p>
<blockquote>
<p>I made a list of significant simplifications in Go over C and C++:</p>
<ul>
<li>regular syntax (don't need a symbol table to …</li></ul></blockquote><p>如果老子会说英语,那么“Less is more”一定出于其口,老子在《道德经》中早就有云“曲则全,枉则直,洼则盈,敝则新,少则得,多则惑”,真乃字字珠玑。</p>
<p>相比于上一个时代的全键盘手机,iPhone只有一个Home键是诠释“Less is more”最好的一个例子:
<img alt="blackberry" src="/static/2017/03-20-blackberry.jpg">
<img alt="iphone" src="/static/2017/03-20-iphone.png"> </p>
<p>Golang的发明人之一Rob Pike则更进一步说<a href="https://commandcenter.blogspot.jp/2012/06/less-is-exponentially-more.html">“Less is exponentially more”</a>并拿Go举例说:</p>
<blockquote>
<p>I made a list of significant simplifications in Go over C and C++:</p>
<ul>
<li>regular syntax (don't need a symbol table to parse)</li>
<li>garbage collection (only)</li>
<li>no header files</li>
<li>explicit dependencies</li>
<li>no circular dependencies</li>
<li>constants are just numbers</li>
<li>...</li>
</ul>
<p>And yet, with that long list of simplifications and missing pieces, Go is, I believe, more expressive than C or C++. <strong>Less can be more.</strong></p>
</blockquote>
<p>相比于C/C++,Go砍和简化了很多feature,Go却可以做的更好,而C++却一直在堆feature、堆复杂度中,或许C++已经掉进了复杂复杂再复杂的死胡同里出不来了。</p>
<blockquote>
<p>In the span of an hour at that talk we heard about something like 35 new features that were being planned. In fact there were many more, but only 35 were described in the talk. Some of the features were minor, of course, but the ones in the talk were at least significant enough to call out. Some were very subtle and hard to understand, like rvalue references, while others are especially C++-like, such as variadic templates, and some others are just crazy, like user-defined literals.</p>
</blockquote>
<p>以致于C++人士会说“没有generic types是什么鬼?”。</p>
<blockquote>
<p>Early in the rollout of Go I was told by someone that he could not imagine working in a language without generic types. As I have reported elsewhere, I found that an odd remark.</p>
</blockquote>
<p>“做加法容易,做减法难”,在iPhone出来之前很难想象手机完全可以没有那么多键(九宫格键盘或全键盘),深谙“Less is more”这也正是乔布斯牛掰之处。</p>
<hr>
<p>题外话:Rob Pike表示本意是想开发Go作为C++的替代语言的,没想到吸引来的却是一大帮Python/Ruby程序员,难怪身边不少Pythoneer都在玩Go,是该学点Go了!</p>
<blockquote>
<p>"What was the biggest surprise you encountered rolling out Go?" I knew the answer instantly: Although we expected C++ programmers to see Go as an alternative, instead most Go programmers come from languages like Python and Ruby. Very few come from C++.</p>
</blockquote>上班时能不能戴耳机?2017-03-18T16:30:00+08:002017-03-18T16:30:00+08:00飞龙tag:feilong.me,2017-03-18:/2017/03/forbidden-headphone.html<p><a href="https://www.v2ex.com/t/348006">新入职一公司, 上班时间不能戴耳机</a>在V站一石激起千层浪,网友意见主要分几派:</p>
<p>甩手走人型:</p>
<ul>
<li>神经病公司,这还不赶紧走</li>
<li>不走等着过年</li>
<li>不走留着转正</li>
<li>离职,下一题</li>
<li>还是赶紧离职吧 这你都能忍</li>
</ul>
<p>出馊主意型:</p>
<ul>
<li>不让戴耳机,那就喇叭外放吧</li>
<li>不能带耳机,那把音响带去公司吧</li>
<li>就说你在听国歌,你有一颗爱国的心</li>
</ul>
<p>半路招聘型:</p>
<ul>
<li>来我这吧,带孩子都没问题,别说带耳机了</li>
<li>我们还需要人</li>
</ul>
<p>少见的表赞同的:</p>
<ul>
<li>这种公司规定很正常。 如果你是一个人 soho,随便你。 但是在公司就不能避免需要交流,当别人有事找你看到你带耳机怎么办?在别人看来就是你不尊重他人的表现。而且你带着耳机如果说话很容易不自觉的大声,也是没礼貌的表现。更何况你耳机里放的是音乐还是股评没人知道,领导当然也不会喜欢这种不可掌控的情况。</li>
</ul>
<p>或许是V站用户群以程序员为主的原因,表赞同的一边倒的被群殴了,大家讨论的重点集中在沟通的有效性和公司管理的人性化上,个人比较认同 @ibegyourpardon 的观点:</p>
<blockquote>
<p>对一部分人来说,戴着耳机给自己制造一种相对的“个人空间”,能有效的提高个人效率和产出,激发灵感。 </p>
<p>特别是程序员群体,很多时候是很需要一个这样的空间进行思维活动 …</p></blockquote><p><a href="https://www.v2ex.com/t/348006">新入职一公司, 上班时间不能戴耳机</a>在V站一石激起千层浪,网友意见主要分几派:</p>
<p>甩手走人型:</p>
<ul>
<li>神经病公司,这还不赶紧走</li>
<li>不走等着过年</li>
<li>不走留着转正</li>
<li>离职,下一题</li>
<li>还是赶紧离职吧 这你都能忍</li>
</ul>
<p>出馊主意型:</p>
<ul>
<li>不让戴耳机,那就喇叭外放吧</li>
<li>不能带耳机,那把音响带去公司吧</li>
<li>就说你在听国歌,你有一颗爱国的心</li>
</ul>
<p>半路招聘型:</p>
<ul>
<li>来我这吧,带孩子都没问题,别说带耳机了</li>
<li>我们还需要人</li>
</ul>
<p>少见的表赞同的:</p>
<ul>
<li>这种公司规定很正常。 如果你是一个人 soho,随便你。 但是在公司就不能避免需要交流,当别人有事找你看到你带耳机怎么办?在别人看来就是你不尊重他人的表现。而且你带着耳机如果说话很容易不自觉的大声,也是没礼貌的表现。更何况你耳机里放的是音乐还是股评没人知道,领导当然也不会喜欢这种不可掌控的情况。</li>
</ul>
<p>或许是V站用户群以程序员为主的原因,表赞同的一边倒的被群殴了,大家讨论的重点集中在沟通的有效性和公司管理的人性化上,个人比较认同 @ibegyourpardon 的观点:</p>
<blockquote>
<p>对一部分人来说,戴着耳机给自己制造一种相对的“个人空间”,能有效的提高个人效率和产出,激发灵感。 </p>
<p>特别是程序员群体,很多时候是很需要一个这样的空间进行思维活动,而非常厌烦被打断。 </p>
<p>通过制造一种相对的隔离空间,提高他人打断他的成本(必须通过 IM ,必须走过去),给自己就制造了一定的缓冲空间,或者有的事就在 IM 上说了,他就更可以通过异步的方式进行回复和沟通。 </p>
<p>你说的这种要走过去拍人家一下进行沟通的事,我相信,一部分是可以通过 IM 和其他方式,并不是要当下那一分钟立刻得到回复的,另一部分呢,可能确实是立刻需要解答的,但并不复杂的问题。这种问题如果频繁,让人不爽,那就不是某一位同事的问题了,而是更多的环节更多的人出了问题。 </p>
<p>总之,我个人是觉得,沟通是非常重要的事,也必不可少,但如果沟通的成本过于低廉(扭个头扯个嗓子就能喊的到),这种沟通看起来方便快捷,却未必是真的高效——现实中更多的时候基本就是低效。 </p>
<p>我个人的经验现在一般是,需要当面沟通并且做到有效传达, IM 不合适的内容,每天安排固定时间段进行面对面坐下来沟通了解。剩余的时间,尽量各自做各自的,这个阶段完了,下一个阶段大家再一起坐下来说事,中间必不可少的环节,基本就用 IM 解决。 </p>
<p>会有人说,总有当面沟通没法解决的问题,必须做的时候解决,怎么办?这不是理由,还是得逼着更进一步的提高沟通效率和有效信息的传达。当然这个环节往往是很多人的问题,而且很多时候是制度上的。 </p>
<p>提高每个人的成本,让每个人觉得和人沟通很麻烦,才会倒逼每个人重视自己的沟通质量。</p>
</blockquote>
<p>但我个人还是非常讨厌工作中用IM沟通的,至于为什么,正好后面 @bianhua 对沟通方式做了进一步的解读:</p>
<blockquote>
<p>传递消息分两类,一类是入侵式的,让接受者中断当前正在进行的工作来接收消息;另一种是非入侵式的,接收者可以知道有一条消息需要处理,但直到他决定去处理,否则可以不理睬。 </p>
<p>入侵式消息通常用在需要紧急响应的情况下,比如用电话、 IM 等(需要实时响应)描述一个简单但需要立即执行的事务,如: XXX 来会议室开会;
非入侵式消息用在非紧急的情况下,比如用邮件、站内通知、短信等。由于你有更多的时间来写下你的文字,所以你可以对要传达的信息进行思考,这不但让你传达的信息更准确,同时也让你有机会对你所传达的信息有所思考。 </p>
<p>这两种传递方式各有自己的做用域,在很多场合下是不可以混用的。比如如果你通过邮件进行紧急事务联系,而对方刚好没有看到邮件,那么这个事务就无法得到及时处理;反过来,如果你用电话去交代一项任务,不但你自己的实时描述可能并不准确,同时接收信息的人可能也不能准确的将信息记录下来,最后导致整个任务失败。 </p>
<p>觉得“吼一嗓子就好”的人,可能是从自己的角度出发,本着将信息递出即完成任务的心理,而不是以完成交接为目标。</p>
</blockquote>
<p>多年前Json Fred在《Rework》书中就有一节专门讲到“Interruption is the enemy of productivity”,提到拍肩膀、IM工具等入侵式的沟通方式是非常有害的,应该尽量少用。</p>
<p>回到耳机这个问题上来,我现在在办公室就不得不经常带着耳机上班,因为隔壁坐着我司客服人员,她们长期和客户电话沟通,噪音较大对工作比较干扰。如果公司也规定上班不能带耳机的话,那我这个码农就真没办法码代码了,只能甩手走人。因为带了耳机,所以沟通主要通过邮件和IM,被打断的不多,码代码的效率杠杠的。</p>Think different2017-03-13T12:50:00+08:002017-03-13T12:50:00+08:00飞龙tag:feilong.me,2017-03-13:/2017/03/think-different.html<p>今天知乎上看到<a href="https://www.zhihu.com/question/56718735/answer/151232947">摩拜、ofo 等共享单车的发展,会对其他行业带来哪些影响?</a>何明科的回答,他的观点独到:</p>
<blockquote>
<p>说一个耸人听闻的吧:共享单车给了房地产商以及房主新的筹码,变现抬高了房价。</p>
</blockquote>
<p>概括下他的理由也很简单:共享单车的便利性让楼盘到地铁的“相对距离”变短了。</p>
<p>何的视角可以说另辟蹊径,不是从常规的自行车产业上下游相关如自行车厂商、配件厂商(锁)、修车从业人员、支付渠道公司、政府交警协警等来看,而是从看似八竿子打不着却又是民众关心的热门话题房地产来看,虽有强行扯上关系的嫌疑,但视角的不同得到的结论也自不同。</p>
<p>说到共享单车,关于单车的乱停乱放问题,红沙发的金老师的观点非常犀利:</p>
<p><img alt="jins-opinion-about-mobike" src="/static/2017/03-13-jins-opinion-about-mobike.jpg"></p>
<p>我们最常听到的是“国民素质差论”然后陷入美国的月亮是不是比中国的圆的口水战中,而金老师独从“城市非机动车停车用地资源的稀缺性”来看这个问题,认为对乱停乱放负主要责任的应是那些做共享单车的商业公司。</p>
<p>我们姑且不论上面两个观点的正确性,它们多少对我们有一些启发。不是说常规的视角看问题就不重要,而是说换一个姿势看世界,或许你会有意外的发现,不人云亦云、学会独立思考,这不正是苹果提倡的“Think different”口号吗?</p><p>今天知乎上看到<a href="https://www.zhihu.com/question/56718735/answer/151232947">摩拜、ofo 等共享单车的发展,会对其他行业带来哪些影响?</a>何明科的回答,他的观点独到:</p>
<blockquote>
<p>说一个耸人听闻的吧:共享单车给了房地产商以及房主新的筹码,变现抬高了房价。</p>
</blockquote>
<p>概括下他的理由也很简单:共享单车的便利性让楼盘到地铁的“相对距离”变短了。</p>
<p>何的视角可以说另辟蹊径,不是从常规的自行车产业上下游相关如自行车厂商、配件厂商(锁)、修车从业人员、支付渠道公司、政府交警协警等来看,而是从看似八竿子打不着却又是民众关心的热门话题房地产来看,虽有强行扯上关系的嫌疑,但视角的不同得到的结论也自不同。</p>
<p>说到共享单车,关于单车的乱停乱放问题,红沙发的金老师的观点非常犀利:</p>
<p><img alt="jins-opinion-about-mobike" src="/static/2017/03-13-jins-opinion-about-mobike.jpg"></p>
<p>我们最常听到的是“国民素质差论”然后陷入美国的月亮是不是比中国的圆的口水战中,而金老师独从“城市非机动车停车用地资源的稀缺性”来看这个问题,认为对乱停乱放负主要责任的应是那些做共享单车的商业公司。</p>
<p>我们姑且不论上面两个观点的正确性,它们多少对我们有一些启发。不是说常规的视角看问题就不重要,而是说换一个姿势看世界,或许你会有意外的发现,不人云亦云、学会独立思考,这不正是苹果提倡的“Think different”口号吗?</p>可叹的tornadoweb.cn用户群2017-03-09T17:50:00+08:002017-03-09T17:50:00+08:00飞龙tag:feilong.me,2017-03-09:/2017/03/tornadoweb-cn-traffic-analytics.html<p><a href="http://www.tornadoweb.cn">tornadoweb.cn</a>是我2011年搭建的<a href="http://www.tornadoweb.org">Tornado</a>中文站,主要是为传播Tornado web framework:</p>
<ol>
<li>当时Tornado官网<a href="http://www.tornadoweb.org">tornadoweb.org</a>放在GAE上,需要翻墙,我提供一个镜像站点给不翻墙的人用。</li>
<li>我找人中文翻译了Tornado 1.2版本的文档,供国人参考</li>
</ol>
<p>6年来这个站点文档没有再更新过,但每天一直保持有200-300的用户访问量(看来当年做了点小事还有点用),今天心血来潮时通过Google Analytics细看了下用户访问来源大吃了一惊:</p>
<p><img alt="tornadoweb.cn traffic" src="/static/2017/03-09-tornadoweb-cn-traffic.jpg"></p>
<p>占绝大部分的流量来自百度搜索,来自Google的搜索只有百度的1/10,用Tornado的筒子们你们想要提升自身技能水平得学会翻墙、远离百度远离百度远离百度啊!!!</p>
<p>我又细追了下其它来源的链接(Referrals),其中来自51cto的<a href="http://3060674.blog.51cto.com/3050674/1683295">第一篇:Python高性能Web框架Tornado原理剖析</a>和来自csdn的<a href="http://blog.csdn.net/fjx1173865548/article/details/54023325">windows下安装tornado</a>非常有趣:</p>
<p>一个把tornadoweb.cn当做官方网站:
<img alt="tornadoweb cn as org" src="/static/2017/03-09-tornadoweb-cn-as-org.jpg"></p>
<p>另一个把tornadoweb.cn当下载来源站:
<img alt="tornadoweb cn download" src="/static/2017/03-09-tornadoweb-cn-download.jpg"></p>
<p>看到这,有没有一股Xcode Ghost事件的既视感?虽然tornadoweb.cn是正儿八经的网站,上面给的下载地址也是Tornado官方的下载地址,但是Xcode Ghost事件中的受害开发者就是这么轻易相信非官方渠道站点,下了被种了病毒的Xcode版本的,我们就不能从Xcode …</p><p><a href="http://www.tornadoweb.cn">tornadoweb.cn</a>是我2011年搭建的<a href="http://www.tornadoweb.org">Tornado</a>中文站,主要是为传播Tornado web framework:</p>
<ol>
<li>当时Tornado官网<a href="http://www.tornadoweb.org">tornadoweb.org</a>放在GAE上,需要翻墙,我提供一个镜像站点给不翻墙的人用。</li>
<li>我找人中文翻译了Tornado 1.2版本的文档,供国人参考</li>
</ol>
<p>6年来这个站点文档没有再更新过,但每天一直保持有200-300的用户访问量(看来当年做了点小事还有点用),今天心血来潮时通过Google Analytics细看了下用户访问来源大吃了一惊:</p>
<p><img alt="tornadoweb.cn traffic" src="/static/2017/03-09-tornadoweb-cn-traffic.jpg"></p>
<p>占绝大部分的流量来自百度搜索,来自Google的搜索只有百度的1/10,用Tornado的筒子们你们想要提升自身技能水平得学会翻墙、远离百度远离百度远离百度啊!!!</p>
<p>我又细追了下其它来源的链接(Referrals),其中来自51cto的<a href="http://3060674.blog.51cto.com/3050674/1683295">第一篇:Python高性能Web框架Tornado原理剖析</a>和来自csdn的<a href="http://blog.csdn.net/fjx1173865548/article/details/54023325">windows下安装tornado</a>非常有趣:</p>
<p>一个把tornadoweb.cn当做官方网站:
<img alt="tornadoweb cn as org" src="/static/2017/03-09-tornadoweb-cn-as-org.jpg"></p>
<p>另一个把tornadoweb.cn当下载来源站:
<img alt="tornadoweb cn download" src="/static/2017/03-09-tornadoweb-cn-download.jpg"></p>
<p>看到这,有没有一股Xcode Ghost事件的既视感?虽然tornadoweb.cn是正儿八经的网站,上面给的下载地址也是Tornado官方的下载地址,但是Xcode Ghost事件中的受害开发者就是这么轻易相信非官方渠道站点,下了被种了病毒的Xcode版本的,我们就不能从Xcode Ghost事件中长点记性么?</p>从iris框架撕逼事件看开源2017-03-08T16:50:00+08:002017-03-08T16:50:00+08:00飞龙tag:feilong.me,2017-03-08:/2017/03/go-iris-framework-debate.html<p><a href="https://github.com/kataras/iris">iris</a>是一个用Go语言写的Web框架(web framework),我截了下Github上iris项目的首页如下图:</p>
<p><img alt="iris" src="/static/2017/03-08-iris.jpg"></p>
<p>作者kataras号称iris是“The <strong>fastest</strong> web framework for Go in (THIS) Earth”,我们来对比看一下另一个Go写的以快著称的Web框架<a href="https://github.com/gin-gonic/gin">Gin</a>,相对没那么狂:</p>
<p><img alt="gin" src="/static/2017/03-08-gin.jpg"></p>
<p>两个都宣称自己快,那到底谁最快呢?于是引出了下面这个帖子<a href="https://github.com/gin-gonic/gin/issues/560">iris is faster</a>,有人在Gin的地盘上说iris更快(注:帖子发生在2016年,它并不是一件新鲜事,只是因为本人刚关注Golang才发现),这个帖子跟我们在技术社区里常看到的“PHP是最好的编程语言”的口水月经撕逼贴几乎如同一辙,但本帖细节非常精彩,我这里简单还原一下:</p>
<ul>
<li>首先dcu说iris更快,建议Gin向iris学</li>
<li>接着Gin主要作者manucorporat说“拿出测试证据来”</li>
<li>CaptainCodeman给出一些测试结果供参考,但说这测试结果并不靠谱</li>
<li>Gin的另一贡献者appleboy说“show me the code”,让我看看哪里不靠谱</li>
<li>第一个转折点来了,CaptainCodeman说“妈蛋,新的iris版本下我的测试代码通不过 …</li></ul><p><a href="https://github.com/kataras/iris">iris</a>是一个用Go语言写的Web框架(web framework),我截了下Github上iris项目的首页如下图:</p>
<p><img alt="iris" src="/static/2017/03-08-iris.jpg"></p>
<p>作者kataras号称iris是“The <strong>fastest</strong> web framework for Go in (THIS) Earth”,我们来对比看一下另一个Go写的以快著称的Web框架<a href="https://github.com/gin-gonic/gin">Gin</a>,相对没那么狂:</p>
<p><img alt="gin" src="/static/2017/03-08-gin.jpg"></p>
<p>两个都宣称自己快,那到底谁最快呢?于是引出了下面这个帖子<a href="https://github.com/gin-gonic/gin/issues/560">iris is faster</a>,有人在Gin的地盘上说iris更快(注:帖子发生在2016年,它并不是一件新鲜事,只是因为本人刚关注Golang才发现),这个帖子跟我们在技术社区里常看到的“PHP是最好的编程语言”的口水月经撕逼贴几乎如同一辙,但本帖细节非常精彩,我这里简单还原一下:</p>
<ul>
<li>首先dcu说iris更快,建议Gin向iris学</li>
<li>接着Gin主要作者manucorporat说“拿出测试证据来”</li>
<li>CaptainCodeman给出一些测试结果供参考,但说这测试结果并不靠谱</li>
<li>Gin的另一贡献者appleboy说“show me the code”,让我看看哪里不靠谱</li>
<li>第一个转折点来了,CaptainCodeman说“妈蛋,新的iris版本下我的测试代码通不过,iris作者又不认我的测试结果,一怒之下我把代码删了”<blockquote>
<p>Sorry @appleboy, after the last update it started failing the unit tests and as the author was unwilling to accept the results anyway so I didn't see any point bothering with it anymore so deleted it all.</p>
</blockquote>
</li>
<li>joeybloggs站出来说“iris并没有作者说的那么快”<blockquote>
<p>It's not as fast as the author portrays</p>
</blockquote>
</li>
<li>于是otraore指出了kataras的测试代码不妥的地方<blockquote>
<p>@kataras The handler for your benchmark (Iris) was still empty and you're comparing different things here. The benchmarks should be comparing routers, not routers with cached enabled.</p>
</blockquote>
</li>
<li>CaptainCodeman跟kataras说你应该接受下大家的批评和改进建议<blockquote>
<p>@kataras You also need to learn to accept criticism or people pointing out errors in your approach - people telling you the results they get doesn't make them liars or "paid" (who do you think is paying them exactly and why?)</p>
</blockquote>
</li>
<li>joeybloggs对CaptainCodeman说“你别费这口舌,我试过,kataras这家伙根本不鸟我:(”<blockquote>
<p>don't waste your breath @CaptainCodeman I gave the same advice in his repo and all he did was "locked and limited conversation to collaborators" then deleted his reddit account and edited his above comment to claim he doesn't have one.</p>
<p>sorry everyone for the noise.</p>
</blockquote>
</li>
<li>一点值得大家学习的小插曲: robvdl指出不要死揪着URL地址路由这一小点的性能不放,它根本不是Web应用的性能瓶颈所在。<blockquote>
<p>This is something I don't really like so much about the Golang community, everyone seems to be obsessed about who has the fastest router. Who cares? Routing is only a tiny portion of the request time, once you start building real application logic on top, it wont matter anymore what router you chose, but the feature set becomes more important. Can we close this issue already... please?</p>
</blockquote>
</li>
<li>关键人物iris作者kataras终于出现了,说了句带感谢的话,结果却引来了另一个神转折,ar3s3ru嘲笑他英语垃圾(kataras是希腊人),一股骂河南人的地域歧视贴气息扑面而来。<blockquote>
<p>@kataras I'm falling in love with your broken english</p>
</blockquote>
</li>
<li>ar3s3ru也是没事找骂,raitucarp马上反击了它,到此此贴已彻底变味。<blockquote>
<p>@ar3s3ru why in this f**ng day, native english speaker people or people that has perfect capability with their english skill, so rude with non native speaker? could you even speak russia? or chinese maybe? I would falling in love if you can speak them perfectly.</p>
</blockquote>
</li>
</ul>
<p>回过头细看下文章开头iris和Gin的Github首页截图对比,就会发现一个非常有意思的现象,两个项目的commit、watch、star、fork数等大体相当,看更新频度项目都比较活跃,但贡献者(contributors)这一项就看出明显差异了,iris只有kataras一个贡献者,而Gin有95个贡献者,很明显Gin是一个真正意义上的社区开源项目,而iris可以认为只是kataras一个人在独舞。进一步挖掘发现iris被推荐好的Go项目的awesome-go给除名了,见<a href="https://github.com/avelino/awesome-go/pull/1135">Remove iris from listing</a>,关键理由是作者对他人贡献的不尊重:</p>
<blockquote>
<p>steals code, editing git history etc. now he removed third-party's licenses. removing it until he understand that third-party's code never stop being third-party's code and can't be stolen and that editing git history to be only contributor while closing users' pull requests is really bad idea. Hope it's temporary.</p>
</blockquote>
<p>基于此,有人大声疾呼大家不要去用iris框架<a href="https://www.reddit.com/r/golang/comments/57w79c/why_you_really_should_stop_using_iris/">Why you REALLY should stop using Iris</a>,从kataras自己所描述的“专注于iris项目”和iris项目代码的更新频度上来看,kataras是确实是一位积极的程序员:</p>
<blockquote>
<p>Iris is a community-driven project, you suggest and I code.</p>
<p>Unlike other repositories, this one is very active. When you post an issue, you get an answer at the next couple of minutes(hours at the worst). If you find a bug, I am obliged to fix that on the same day.</p>
</blockquote>
<p>可问题出就出在他自己做着Open source的事却缺乏Open的心态,不虚心接受他人的建议和批评、不尊重他人的代码贡献,于己于项目都是非常不利的。虽然我看完了iris的官方文档觉得iris还不错,但真要我选Go的Web框架,我肯定不会选择iris。</p>
<hr>
<p>PS:iris号称自己是最快(fastest),若在我朝按新广告法已是违规了。</p>果断清理了一批微信好友2017-03-06T15:40:00+08:002017-03-06T15:40:00+08:00飞龙tag:feilong.me,2017-03-06:/2017/03/delete-contacts-on-wechat.html<p>最近一段时间发现自己越来越少打开微信朋友圈,甚至出现几天没开的情况,这在以前是件不敢想象的事情,虽然说不看朋友圈身上并没有掉块肉,但的确有时会漏掉一些亲朋好友的重要动态。现在的朋友圈早已不是之前的朋友圈,里面充斥着各种不感兴趣、不相关的内容,信息获取效率大大降低,这也是为什么点进朋友圈去看的欲望都快没了。</p>
<p>今天看到《社交红利》的作者徐志斌在知乎问题<a href="https://www.zhihu.com/question/56721329/answer/150180612">微信删除联系人和拉黑时心理个是什么??</a>中的回答触动了我,不看微信通讯录不知道,一看着实吓一跳,我居然加了超过800好友,很多人看昵称根本记不起是谁,还有一些好友一句话都没说过,可能只是某些场合互加了好友而已。这些没联系的联系人一直就这样保留着没删,总认为或许哪天会需要去联系,而实际上从来就没再联系过,打个不恰当的比喻就像家里各角落藏的一些不用的东西一样,你总觉得哪天能用上,实际上除了藏在那布满灰尘外毫无用处,只会类似的“垃圾”越积越多,要找真正需要的东西的时候它们就成了阻碍,朋友圈的情形何尝不是如此啊,不及时的删除不必要的好友、屏蔽一些人不感兴趣的人的动态,通过朋友圈获取信息的效率就大打折扣。</p>
<p>在下手清理掉了200微信好友和屏蔽一些人的动态后,再刷朋友圈顿觉神清气爽,朋友圈早该好好清理清理了,而且要持续的清理。</p>
<p>PS:还剩600人是不是还是有点多?Path最初的50好友上限对朋友圈而言想想也挺科学。</p><p>最近一段时间发现自己越来越少打开微信朋友圈,甚至出现几天没开的情况,这在以前是件不敢想象的事情,虽然说不看朋友圈身上并没有掉块肉,但的确有时会漏掉一些亲朋好友的重要动态。现在的朋友圈早已不是之前的朋友圈,里面充斥着各种不感兴趣、不相关的内容,信息获取效率大大降低,这也是为什么点进朋友圈去看的欲望都快没了。</p>
<p>今天看到《社交红利》的作者徐志斌在知乎问题<a href="https://www.zhihu.com/question/56721329/answer/150180612">微信删除联系人和拉黑时心理个是什么??</a>中的回答触动了我,不看微信通讯录不知道,一看着实吓一跳,我居然加了超过800好友,很多人看昵称根本记不起是谁,还有一些好友一句话都没说过,可能只是某些场合互加了好友而已。这些没联系的联系人一直就这样保留着没删,总认为或许哪天会需要去联系,而实际上从来就没再联系过,打个不恰当的比喻就像家里各角落藏的一些不用的东西一样,你总觉得哪天能用上,实际上除了藏在那布满灰尘外毫无用处,只会类似的“垃圾”越积越多,要找真正需要的东西的时候它们就成了阻碍,朋友圈的情形何尝不是如此啊,不及时的删除不必要的好友、屏蔽一些人不感兴趣的人的动态,通过朋友圈获取信息的效率就大打折扣。</p>
<p>在下手清理掉了200微信好友和屏蔽一些人的动态后,再刷朋友圈顿觉神清气爽,朋友圈早该好好清理清理了,而且要持续的清理。</p>
<p>PS:还剩600人是不是还是有点多?Path最初的50好友上限对朋友圈而言想想也挺科学。</p>吃着碗里,看着碗外2017-03-03T18:40:00+08:002017-03-03T18:40:00+08:00飞龙tag:feilong.me,2017-03-03:/2017/03/comment-mogujie-meilishuo.html<p><a href="https://www.huxiu.com/article/183639.html">频曝裁员收入下滑,这一年蘑菇街美丽说到底遭遇了什么?</a>文中谈到蘑菇街和美丽说合并之后出现高管离职、撕逼、裁员、交易额下滑等问题,以后或许会被商学院当成经典案例来讲,他们的合并成功与否自有人去评说,这里对此不去展开,在我看来文中比较有价值的是下面这段话:</p>
<blockquote>
<p>“看看后来唯品会创造的资本市场奇迹,再看看蘑菇街、美丽说,他们在一个小众市场中拼第一名,却没有看到更广阔的蓝海市场。反应过来的时候,已经被新兴的互联网公司占下山头。从这点来看,两家公司走向没落一点都不可惜。”李明表示,这两家公司在后来至少有2次转型机会,一次机会是网红电商,一次机会是从电商导购转型电商平台。这两次机会中抓住任何一次,都可以将公司推向新的高度,可是转型的时机太晚了。</p>
</blockquote>
<p>一个企业在自己的优势领域拼杀巩固自己的市场本无可厚非,但为此耗费太多精力而忽视对其它可能市场的开拓就有可能为自己的发展埋下地雷,我们见过太多公司在盛极一时后迅速消失,文中提到的开心网就是一个典型案例,“吃着碗里,看着碗外”或许才是正确的姿势,毕竟旁边通常还有一口大锅。</p><p><a href="https://www.huxiu.com/article/183639.html">频曝裁员收入下滑,这一年蘑菇街美丽说到底遭遇了什么?</a>文中谈到蘑菇街和美丽说合并之后出现高管离职、撕逼、裁员、交易额下滑等问题,以后或许会被商学院当成经典案例来讲,他们的合并成功与否自有人去评说,这里对此不去展开,在我看来文中比较有价值的是下面这段话:</p>
<blockquote>
<p>“看看后来唯品会创造的资本市场奇迹,再看看蘑菇街、美丽说,他们在一个小众市场中拼第一名,却没有看到更广阔的蓝海市场。反应过来的时候,已经被新兴的互联网公司占下山头。从这点来看,两家公司走向没落一点都不可惜。”李明表示,这两家公司在后来至少有2次转型机会,一次机会是网红电商,一次机会是从电商导购转型电商平台。这两次机会中抓住任何一次,都可以将公司推向新的高度,可是转型的时机太晚了。</p>
</blockquote>
<p>一个企业在自己的优势领域拼杀巩固自己的市场本无可厚非,但为此耗费太多精力而忽视对其它可能市场的开拓就有可能为自己的发展埋下地雷,我们见过太多公司在盛极一时后迅速消失,文中提到的开心网就是一个典型案例,“吃着碗里,看着碗外”或许才是正确的姿势,毕竟旁边通常还有一口大锅。</p>博客复活2017-03-03T17:40:00+08:002017-03-03T17:40:00+08:00飞龙tag:feilong.me,2017-03-03:/2017/03/blog-resurrection.html<p>本博客最初于2010年用WordPress搭建开博,初期主要写Python相关的技术为主,逐步演变成记录工作、生活、学习的碎碎念。WordPress虽然强大但实在太慢,我的vps上还跑了一些站点和服务,后来访问站点经常卡死就想弃用,只一直在线挂着,之后转移到微信公共账号上写了一段时间,不大喜欢微信公共账号相对封闭的体系,陈浩在<a href="http://coolshell.cn/articles/17391.html">为什么我不在微信公众号上写文章</a>有相似的观点,微信公共号在2016年以后我也停更了,但是我用博客的方式记录的需求一直很强烈,受不了WordPress系统,今天我终于用用Python开发的<a href="https://github.com/getpelican/pelican">Pelican</a>静态博客系统和<a href="https://pages.github.com">Github Pages</a>替代了原来的WordPress,博客站点变得清爽和轻量级多了,因为是静态站点了访问速度非常快,重要的是以后的文章可以直接用markdown格式在Sublime Txt里写,然后提交到Github用版本库管理起来,正式发布则只需要敲一行fab命令,彻底告别臃肿的WordPress管理后台。</p>
<p>Pelican可以直接导入WordPress站点的文章,迁移到Pelican我只花了少量时间来修复部分文章里面的标签、关键字和文档格式等,几乎是无缝迁移,这也是Pelican的强大之处,目前我已把原站点的所有文章迁移过来并保持了原链接不变。</p>
<p>同时我也把原来在微信公共账号写的一些文章转成了markdown格式迁移了过来,将老的站点文章和微信公共账号的文章合二为一,从此本博客复活,或勤或懒我将继续保持更新。</p>
<p>不知道是有意还是无意我挑中了名字跟Felinx有点近的<a href="https://github.com/alexandrevicenzi/flex">Flex</a>主题,在此基础上我做了一点点小调整,将原来的Archives文章标题列表页挪用成首页,而不是标准的包含文章摘要内容的列表页,因为每篇文章内容不同,文章都带摘要的首页整体感觉比较混乱个人不是很喜欢,故改成了现在的模式,相对更小清新些 …</p><p>本博客最初于2010年用WordPress搭建开博,初期主要写Python相关的技术为主,逐步演变成记录工作、生活、学习的碎碎念。WordPress虽然强大但实在太慢,我的vps上还跑了一些站点和服务,后来访问站点经常卡死就想弃用,只一直在线挂着,之后转移到微信公共账号上写了一段时间,不大喜欢微信公共账号相对封闭的体系,陈浩在<a href="http://coolshell.cn/articles/17391.html">为什么我不在微信公众号上写文章</a>有相似的观点,微信公共号在2016年以后我也停更了,但是我用博客的方式记录的需求一直很强烈,受不了WordPress系统,今天我终于用用Python开发的<a href="https://github.com/getpelican/pelican">Pelican</a>静态博客系统和<a href="https://pages.github.com">Github Pages</a>替代了原来的WordPress,博客站点变得清爽和轻量级多了,因为是静态站点了访问速度非常快,重要的是以后的文章可以直接用markdown格式在Sublime Txt里写,然后提交到Github用版本库管理起来,正式发布则只需要敲一行fab命令,彻底告别臃肿的WordPress管理后台。</p>
<p>Pelican可以直接导入WordPress站点的文章,迁移到Pelican我只花了少量时间来修复部分文章里面的标签、关键字和文档格式等,几乎是无缝迁移,这也是Pelican的强大之处,目前我已把原站点的所有文章迁移过来并保持了原链接不变。</p>
<p>同时我也把原来在微信公共账号写的一些文章转成了markdown格式迁移了过来,将老的站点文章和微信公共账号的文章合二为一,从此本博客复活,或勤或懒我将继续保持更新。</p>
<p>不知道是有意还是无意我挑中了名字跟Felinx有点近的<a href="https://github.com/alexandrevicenzi/flex">Flex</a>主题,在此基础上我做了一点点小调整,将原来的Archives文章标题列表页挪用成首页,而不是标准的包含文章摘要内容的列表页,因为每篇文章内容不同,文章都带摘要的首页整体感觉比较混乱个人不是很喜欢,故改成了现在的模式,相对更小清新些。</p>
<hr>
<p>关于Pelican请参考:</p>
<ul>
<li><a href="http://www.wengweitao.com/shi-yong-pelican-github-pagesda-jian-ge-ren-bo-ke.html">使用Pelican + Github Pages搭建个人博客</a></li>
<li><a href="http://docs.getpelican.com/en/stable/">Pelican Documentation</a></li>
<li><a href="http://russell.ballestrini.net/migrating-from-wordpress-to-pelican/">Migrating from WordPress to Pelican</a></li>
</ul>一封来自丁香园robbin的招(la)聘(ji)邮件2017-03-02T10:20:00+08:002017-03-02T10:20:00+08:00飞龙tag:feilong.me,2017-03-02:/2017/03/dxy-robbin-email.html<p>我从来没有用过丁香园的产品,今天我的Gmail邮箱却收到了以robbin的名义dxy的邮件地址发的丁香园招聘邮件,如下图:</p>
<p><img alt="dxy-robbin-email" src="/static/2017/03-02-dxy-robbin-email.jpg"></p>
<p>本质上这是一封spam邮件,邮件以robbin个人的名义发出,简历接收地址留的是robbin的个人Gmail而不是他在公司邮箱,邮件中的“和robbin一起工作、弹性工作时间、舒适的办公环境并附照片”等内容刻意将招聘广告包装的温馨、高大上,但这改变不了这封邮件的spam本质。对于未订阅渠道来的垃圾邮件,作为多少有点代码洁癖的程序员心理我是抵触的,针对程序员群体发这样的招聘邮件效果我个人持怀疑态度,robbin本身是一位高水平的程序员,发送这封邮件之前应该是经过深思熟虑的,个人不负责任的猜想丁香园在去年和Fenng撕了一番之后,招聘程序员变得不如以前顺利了,robbin所以才会出此下策。虽然像我这样反感这封邮件的人有之,但也一定会有人正好命中其换工作的需求投递简历给robbin的,招到了员工和丢了丁香园在一部分心中的口碑,个中得失只有让robbin去品了。</p>
<p>另外,邮件开头就特意提到robbin自己的JavaEye创始人身份,丁香园并没有我的任何足迹,这里我冒昧猜这是拉了JavaEye的用户数据给JavaEye的一批老用户发的,如果真是如此就牵出另一个有意思的问题,JavaEye已被CSDN收购更名成了ITeye,在丁香园工作的robbin用JavaEye的数据貌似也不合适(如果他们之间有协议另说)。</p>
<p>2017/3/3更新: 针对此事我发到v2ex上的帖子<a href="https://www.v2ex.com/t/344276">https://www.v2ex.com/t/344276</a>引出一个丁香园新近离职的程序员在知乎上的吐槽<a href="https://www.zhihu.com/question/22046494/answer/59855377">https://www.zhihu.com/question/22046494 …</a></p><p>我从来没有用过丁香园的产品,今天我的Gmail邮箱却收到了以robbin的名义dxy的邮件地址发的丁香园招聘邮件,如下图:</p>
<p><img alt="dxy-robbin-email" src="/static/2017/03-02-dxy-robbin-email.jpg"></p>
<p>本质上这是一封spam邮件,邮件以robbin个人的名义发出,简历接收地址留的是robbin的个人Gmail而不是他在公司邮箱,邮件中的“和robbin一起工作、弹性工作时间、舒适的办公环境并附照片”等内容刻意将招聘广告包装的温馨、高大上,但这改变不了这封邮件的spam本质。对于未订阅渠道来的垃圾邮件,作为多少有点代码洁癖的程序员心理我是抵触的,针对程序员群体发这样的招聘邮件效果我个人持怀疑态度,robbin本身是一位高水平的程序员,发送这封邮件之前应该是经过深思熟虑的,个人不负责任的猜想丁香园在去年和Fenng撕了一番之后,招聘程序员变得不如以前顺利了,robbin所以才会出此下策。虽然像我这样反感这封邮件的人有之,但也一定会有人正好命中其换工作的需求投递简历给robbin的,招到了员工和丢了丁香园在一部分心中的口碑,个中得失只有让robbin去品了。</p>
<p>另外,邮件开头就特意提到robbin自己的JavaEye创始人身份,丁香园并没有我的任何足迹,这里我冒昧猜这是拉了JavaEye的用户数据给JavaEye的一批老用户发的,如果真是如此就牵出另一个有意思的问题,JavaEye已被CSDN收购更名成了ITeye,在丁香园工作的robbin用JavaEye的数据貌似也不合适(如果他们之间有协议另说)。</p>
<p>2017/3/3更新: 针对此事我发到v2ex上的帖子<a href="https://www.v2ex.com/t/344276">https://www.v2ex.com/t/344276</a>引出一个丁香园新近离职的程序员在知乎上的吐槽<a href="https://www.zhihu.com/question/22046494/answer/59855377">https://www.zhihu.com/question/22046494/answer/59855377</a>,看来是真的急缺人了才发这邮件了。</p>三人行,莫为人师2016-04-02T22:00:00+08:002016-04-02T22:00:00+08:00飞龙tag:feilong.me,2016-04-02:/2016/04/you-are-not-coach.html<p>昨天下午我去了一趟一位老朋友公司,正好赶上他们要开会讨论产品原型设计,于是坐下来旁听,在不是很了解产品需求的情况下,听着听着不自觉的我就插起了嘴来,从我以往的产品经验上对于一些设计点提出了反对意见,内心里打上了几个❌❌</p>
<p><img alt="wrong" src="/static/2016/04/wrong.gif"></p>
<p>最后还就MVP和高保真原型的一些观点和一位朋友争论了起来。类似的事情在上一周受邀参加方糖小镇的产品需求讨论会上也发生过,姑且不论我的经验是否适合于对方和我说的观点是否正确,细想起来我已犯了人之患,其患在好为人师。</p>
<p>我常用孔子的话“三人行,必有我师焉”来提醒自己要虚心向身边的人学习,也常用这句话来劝导在抱怨“身边没有厉害的人可学习”的朋友。当我带着必有我师的眼光来看人的时候,发现他们都有其独特的闪光点,特别是身边的一群90后,在他们所喜欢的事情上,他们比我这80一代更专注、更狂热、也更有他们的话语权,好比昨天上午两位90后就好好的给我们一帮大叔们普及了二次元知识,只不过当时的我……</p>
<p><img alt="stun" src="/static/2016/04/stun.jpg"></p>
<p>三人行必有我师,反之,或许三人行必有师我者,别人可以师我那是我的荣幸,但我自己不可有“师”者的姿态,与人交流更多的应该是分享而不是指点。三人行,莫为人师,戒之戒之以自勉!</p><p>昨天下午我去了一趟一位老朋友公司,正好赶上他们要开会讨论产品原型设计,于是坐下来旁听,在不是很了解产品需求的情况下,听着听着不自觉的我就插起了嘴来,从我以往的产品经验上对于一些设计点提出了反对意见,内心里打上了几个❌❌</p>
<p><img alt="wrong" src="/static/2016/04/wrong.gif"></p>
<p>最后还就MVP和高保真原型的一些观点和一位朋友争论了起来。类似的事情在上一周受邀参加方糖小镇的产品需求讨论会上也发生过,姑且不论我的经验是否适合于对方和我说的观点是否正确,细想起来我已犯了人之患,其患在好为人师。</p>
<p>我常用孔子的话“三人行,必有我师焉”来提醒自己要虚心向身边的人学习,也常用这句话来劝导在抱怨“身边没有厉害的人可学习”的朋友。当我带着必有我师的眼光来看人的时候,发现他们都有其独特的闪光点,特别是身边的一群90后,在他们所喜欢的事情上,他们比我这80一代更专注、更狂热、也更有他们的话语权,好比昨天上午两位90后就好好的给我们一帮大叔们普及了二次元知识,只不过当时的我……</p>
<p><img alt="stun" src="/static/2016/04/stun.jpg"></p>
<p>三人行必有我师,反之,或许三人行必有师我者,别人可以师我那是我的荣幸,但我自己不可有“师”者的姿态,与人交流更多的应该是分享而不是指点。三人行,莫为人师,戒之戒之以自勉!</p>奥来韩式烤肉店老板的产品之道2015-12-07T22:00:00+08:002015-12-07T22:00:00+08:00飞龙tag:feilong.me,2015-12-07:/2015/12/aolai-product-philosophy.html<p>先来见识下正在大快朵颐的吃货老板(图正中)</p>
<p><img alt="aolai" src="/static/2015/12/aolai.jpg"></p>
<p>接下来是我嘴馋的蚬子,我主要好他店里这一口</p>
<p><img alt="shell" src="/static/2015/12/shell.jpg"></p>
<p>从9月份开始,我就隔三差五的打电话问店老板“什么时候有烤蚬子”,直到前几天终于得到老板肯定的答复,跑去饱餐了一顿。大概你会觉不屑,蚬子哪个季节没有、哪个店里不卖、何必要守着这家店吃呢?细嚼之下我才发现这家店自有其独到之处。</p>
<p>奥来是我小区附近的一家并不起眼的韩式烤肉店,老板朝鲜族,来自黑龙江。店里用的蚬子只每年的11月-次年3月左右直接从丹东进货,虽然全年上海市场都有蚬子卖,但老板只认这个时节丹东的蚬子,其它时候老板宁可不卖这道菜。老板每次进货不多,就40斤,只够卖3天,蚬子放的时间一长就不新鲜了,口味大打折扣,所以老板选择勤进快消,宁愿没得卖也不卖不新鲜的货。老板说“现在还没有”,是我馋虫作祟电询老板时得到最多的答复。</p>
<p>店里的泡菜、萝卜、花生等小配菜在韩式店里算“标配”了,并不稀罕,可是这里的吃起来却总觉别有风味,问了老板才知道,原来店里这些小菜也都是店里自己做的,而不是像其他店家那样直接进成品,老板说这样既经济也好吃,他还挺喜欢自己做(我看也是个苦命老板,哈哈)。店里所有的酱料也是店里自制的,老板会逐个给食客介绍这个酱配蚬子、那个酱配五花肉、那个酱配牛舌吃等等,各有不同 …</p><p>先来见识下正在大快朵颐的吃货老板(图正中)</p>
<p><img alt="aolai" src="/static/2015/12/aolai.jpg"></p>
<p>接下来是我嘴馋的蚬子,我主要好他店里这一口</p>
<p><img alt="shell" src="/static/2015/12/shell.jpg"></p>
<p>从9月份开始,我就隔三差五的打电话问店老板“什么时候有烤蚬子”,直到前几天终于得到老板肯定的答复,跑去饱餐了一顿。大概你会觉不屑,蚬子哪个季节没有、哪个店里不卖、何必要守着这家店吃呢?细嚼之下我才发现这家店自有其独到之处。</p>
<p>奥来是我小区附近的一家并不起眼的韩式烤肉店,老板朝鲜族,来自黑龙江。店里用的蚬子只每年的11月-次年3月左右直接从丹东进货,虽然全年上海市场都有蚬子卖,但老板只认这个时节丹东的蚬子,其它时候老板宁可不卖这道菜。老板每次进货不多,就40斤,只够卖3天,蚬子放的时间一长就不新鲜了,口味大打折扣,所以老板选择勤进快消,宁愿没得卖也不卖不新鲜的货。老板说“现在还没有”,是我馋虫作祟电询老板时得到最多的答复。</p>
<p>店里的泡菜、萝卜、花生等小配菜在韩式店里算“标配”了,并不稀罕,可是这里的吃起来却总觉别有风味,问了老板才知道,原来店里这些小菜也都是店里自己做的,而不是像其他店家那样直接进成品,老板说这样既经济也好吃,他还挺喜欢自己做(我看也是个苦命老板,哈哈)。店里所有的酱料也是店里自制的,老板会逐个给食客介绍这个酱配蚬子、那个酱配五花肉、那个酱配牛舌吃等等,各有不同,独具匠心。</p>
<p><img alt="peanut" src="/static/2015/12/peanut.jpg"></p>
<p><img alt="luobo" src="/static/2015/12/luobo.jpg"></p>
<p>聊的多了,老板提到店里菜单上的菜其实不到店刚开张时的一半,老板一方面不断的将菜单中卖的不好菜品去掉;另一方面把受欢迎的菜做精做好。精简菜单的同时也保证了原材料的新鲜度,没有卖不动的菜过期了还在卖的嘛!另外,店里从不搞什么大众点评啊美团啊什么的团购,这也是我极为佩服老板的一点,想来如此执着细心之人,有这样的选择也并不奇怪。</p>
<p>买单的时候,发现收银台前摆着几箱大米,就是店里自用的东北米,客人觉得米饭好吃,就可以直接从店里买点扛回家。</p>
<p><img alt="rice" src="/static/2015/12/rice.jpg"></p>
<p>到这里,我打从心底钦佩起奥来老板的经营之道来,不单单是因为他经营好了自己这家韩式烤肉店,更是他的每个细节处,蕴含了朴素的产品之道:</p>
<ul>
<li>
<p>搔自己的痒:
老板本身就是一个大吃货,讲起吃来头头是道,我好几次去吃都碰到他自己也在烤蚬子吃。老板不吃市面上能买到的“不合口味”,而是做自己喜欢的泡菜。</p>
</li>
<li>
<p>重产品质量:
老板只选择最当季最好的蚬子;只销售在原材料保鲜期内的菜;连小配菜上都下足功夫自制,以保证高品质。不做团购,希望你喜欢的是我的美味,而不是我的实惠。</p>
</li>
<li>
<p>坚持做减法:
菜单上不可能写上所有人爱吃的菜,专注做好最能提升食客体验和店里最有竞争力的菜品,其它的宁愿放弃不做。</p>
</li>
<li>
<p>体验式消费:
让客人吃到好吃的食材之后,店内直接提供原料可购买,不但店里多一份收入,也给客人提供了愉悦和便利。在吃货大快朵颐的场景下,食客很容易产生购买行为,看起来其实并不是在“卖”大米,更像是因为客人喜欢,所以老板就从东北顺便给客人“捎带”了些来。</p>
</li>
</ul>
<p>最后附互联网创业经典书籍《Rework》中的两段截图:</p>
<p><img alt="scrtch-itch" src="/static/2015/12/scratch-itch.jpg"></p>
<p><img alt="scrtch-itch2" src="/static/2015/12/scratch-itch2.jpg"></p>
<p>我估计这老板多半是没有看过这本书,但是他的一些理念跟书中的一些点竟是惊人的吻合。也是,毕竟人家好歹也是一个CEO,要是干互联网说不定可以秒了我,该多向人家学习啊!</p>
<hr>
<p>鸣谢:本文部分文字经Sydney同学整理</p>一封旧邮件:关于四国第三方辅助程序2015-11-23T10:00:00+08:002015-11-23T10:00:00+08:00飞龙tag:feilong.me,2015-11-23:/2015/11/siguozhanji-feedback-email.html<p>四国开发、运营团队你们好!</p>
<p>我是一名忠实的四国玩家(非R),同时在多个区有同名账号(灰太龙),你们也有可能知道有我这么个玩家,我从第一天接触四国到现在没有一天不上四国,但限于四国有些地方比较耗时间,比如打魔神、势力战等,因为喜欢四国但工作忙又没有太多时间来玩四国,因此我陆陆续续自己开发了自动打魔神、自动刷塔、分批次自动打竞技场、24小时监控贼并自动找合适的打、自动送和获取好友体力、自动探索地图防体力溢出并找贼,还有最近刚开发的势力战全程刷CD自动找热点加入战斗等辅助功能,其它小的功能如冥想、购买金币包、改名等还有不少,这些功能主要以方便玩家完成一些耗时的工作为目地,基本是在手动玩的游戏规则之内,没有去恶意破坏游戏规则。</p>
<p>开始辅助程序只是给我自己玩的号使用,但是因为辅助功能很实用,陆续有很多朋友让我帮他们开辅助,包括多个区的一些TOP玩家,其中也不乏一些大的RMB玩家,因为我都是帮一些游戏中的熟人朋友开,我也没有打算把它拿来做任何商业行为,因此我也没有向任何人收取服务费用。因为我开发的辅助功能齐全,也比较方便、智能,用过的朋友口口相传,现在来找我开辅助的人越来越多,现在我的问题是:</p>
<ol>
<li>我自己给自己的账号是否可以开辅助?</li>
<li>我是否可以在不商业化的情况下给朋友开辅助?</li>
<li>四国是否允许普通玩家使用第三方辅助?</li>
<li>既然有这么多用户有这方面的需求,四国官方是否有考虑出官方的辅助来方便玩家?包括你们开发的其它游戏如XXXX、新出的XXXX等亦然。</li>
<li>另一方面,四国服务器端基于HTTP而不是HTTPS,理论上一个稍微有点经验的web开发人员都有能力开发四国的辅助,当然了 …</li></ol><p>四国开发、运营团队你们好!</p>
<p>我是一名忠实的四国玩家(非R),同时在多个区有同名账号(灰太龙),你们也有可能知道有我这么个玩家,我从第一天接触四国到现在没有一天不上四国,但限于四国有些地方比较耗时间,比如打魔神、势力战等,因为喜欢四国但工作忙又没有太多时间来玩四国,因此我陆陆续续自己开发了自动打魔神、自动刷塔、分批次自动打竞技场、24小时监控贼并自动找合适的打、自动送和获取好友体力、自动探索地图防体力溢出并找贼,还有最近刚开发的势力战全程刷CD自动找热点加入战斗等辅助功能,其它小的功能如冥想、购买金币包、改名等还有不少,这些功能主要以方便玩家完成一些耗时的工作为目地,基本是在手动玩的游戏规则之内,没有去恶意破坏游戏规则。</p>
<p>开始辅助程序只是给我自己玩的号使用,但是因为辅助功能很实用,陆续有很多朋友让我帮他们开辅助,包括多个区的一些TOP玩家,其中也不乏一些大的RMB玩家,因为我都是帮一些游戏中的熟人朋友开,我也没有打算把它拿来做任何商业行为,因此我也没有向任何人收取服务费用。因为我开发的辅助功能齐全,也比较方便、智能,用过的朋友口口相传,现在来找我开辅助的人越来越多,现在我的问题是:</p>
<ol>
<li>我自己给自己的账号是否可以开辅助?</li>
<li>我是否可以在不商业化的情况下给朋友开辅助?</li>
<li>四国是否允许普通玩家使用第三方辅助?</li>
<li>既然有这么多用户有这方面的需求,四国官方是否有考虑出官方的辅助来方便玩家?包括你们开发的其它游戏如XXXX、新出的XXXX等亦然。</li>
<li>另一方面,四国服务器端基于HTTP而不是HTTPS,理论上一个稍微有点经验的web开发人员都有能力开发四国的辅助,当然了,HTTPS的也是可以的,只是门槛稍微高一点点而已,而事实上淘宝网上之前也是有其它的人在卖四国辅助的,从我个人了解情况来看用的人还不在少数,屌丝和RMB玩家都有。如果你们原则上不允许第三方辅助的话,你们是否有去考虑好的安全防范措施在将来对辅助进行封禁或限制甚至是诉诸于法律手段呢?</li>
</ol>
<p>请收到此邮件的客服人员稍微慎重一点来处理本邮件,最好请转发你们四国团队的一些主要负责人讨论后给我这名特别一点的玩家一个准确的官方的答复,我将根据你们的官方回答来决定是否能继续开发&使用、部分关停或完全关停我开发的辅助。如果我之前的行为对四国游戏造成了破坏,我这里也向你们表示一下我的歉意,因为一直不清楚四国官方对辅助程序的处理态度,特发此邮件征询,真诚期盼你们的答复,谢谢!</p>
<p>By:灰太龙,一名忠实的四国玩家,一名移动互联网从业人员,顺祝四国越办越好!</p>
<hr>
<p>刚找材料时翻到这封邮件后,原邮件写于近两年前,之所以把他发到这来,是提醒自己:如果收到类似于这样的用户的反馈,我一定要跟TA好好沟通一把,甚至把人请到公司来。愿意给产品反馈意见或问题的是少数派,更多的人直接用脚投票,能写长邮件联系客服反馈意见的用户一定要重视起来,他们是不可多得的金质用户。</p>
<p>PS:游戏用四国代指,隐去全名,懂的人自然动,不懂的也不用懂:)</p>《增长黑客》:一本感觉特别亲近的创业书2015-08-08T10:00:00+08:002015-08-08T10:00:00+08:00飞龙tag:feilong.me,2015-08-08:/2015/08/growth-hacker.html<p><img alt="growth-hacker" src="/static/2015/08/growth-hacker.jpg"></p>
<p>至今为止我所读过的所有书里,最感亲近的一本书非范老师的新书《增长黑客》莫属,这种感觉就好比走在上海熙熙攘攘的街上突然听到了一声熟悉的家乡话,当拿到书看到封面上那些熟悉的人名时,这种感觉就扑面而来。</p>
<p>《增长黑客》是前盛大创新院同事范冰范老师在工作之余历时一年之久写就的一本关于创业公司如何四两拨千斤巧妙增长的书,范冰虽然比我小好几岁,我还是习惯性的称他范老师,范老师是互联网行业知名的博主,在写作、互联网产品、Growth等多方面都是我事实上的老师。我在做之前的游戏玩家社交APP的时候,曾在魔都和帝都多次向范老师请教,范老师跟我分享过他在做“追TA”时的一些经验,这些经验范老师总结成文在本书中的“追TA”案例中可以找到。</p>
<p>如范老师自己所述,这是一本献给有梦想的创业者的书。</p>
<p><img alt="preface-dream" src="/static/2015/08/preface-dream.jpg"></p>
<p>每个创业公司都会经历从0到1的过程,《增长黑客》用大量详实的国内外的关于用户、收入增长的实际案例,给我们好好的上了一课,Hotmail、Instagram、Airbnb、Quora、Linkedin、WiFi万能钥匙、追TA等的案例读来不禁令人拍案叫绝。</p>
<p>近几年来,O2O市场火爆,相应的资本市场凶残,大量创业公司和资本涌入O2O领域,竞争异常激烈,极大的提升了本地市场的用户推广成本。我的创业项目“呱呱”(一款基于强地理位置的本地社交应用)正处于用户从0到1的阶段,产品所特有的强位置属性(方圆5.20公里 …</p><p><img alt="growth-hacker" src="/static/2015/08/growth-hacker.jpg"></p>
<p>至今为止我所读过的所有书里,最感亲近的一本书非范老师的新书《增长黑客》莫属,这种感觉就好比走在上海熙熙攘攘的街上突然听到了一声熟悉的家乡话,当拿到书看到封面上那些熟悉的人名时,这种感觉就扑面而来。</p>
<p>《增长黑客》是前盛大创新院同事范冰范老师在工作之余历时一年之久写就的一本关于创业公司如何四两拨千斤巧妙增长的书,范冰虽然比我小好几岁,我还是习惯性的称他范老师,范老师是互联网行业知名的博主,在写作、互联网产品、Growth等多方面都是我事实上的老师。我在做之前的游戏玩家社交APP的时候,曾在魔都和帝都多次向范老师请教,范老师跟我分享过他在做“追TA”时的一些经验,这些经验范老师总结成文在本书中的“追TA”案例中可以找到。</p>
<p>如范老师自己所述,这是一本献给有梦想的创业者的书。</p>
<p><img alt="preface-dream" src="/static/2015/08/preface-dream.jpg"></p>
<p>每个创业公司都会经历从0到1的过程,《增长黑客》用大量详实的国内外的关于用户、收入增长的实际案例,给我们好好的上了一课,Hotmail、Instagram、Airbnb、Quora、Linkedin、WiFi万能钥匙、追TA等的案例读来不禁令人拍案叫绝。</p>
<p>近几年来,O2O市场火爆,相应的资本市场凶残,大量创业公司和资本涌入O2O领域,竞争异常激烈,极大的提升了本地市场的用户推广成本。我的创业项目“呱呱”(一款基于强地理位置的本地社交应用)正处于用户从0到1的阶段,产品所特有的强位置属性(方圆5.20公里)依赖于一定位置范围内的用户密度,我们要达到此用户密度目标不能跟这些挥舞着美金的公司直面竞争抢用户,必须借助于巧力四两拨千斤,《增长黑客》给我提供了一套用户增长的思想武器,也提供了一些实际操作案例可供案边参考。《增长黑客》是我本年度读到的不可多得的一本好书了,已随手送出了两本给同在创业的朋友。</p>
<p>读本书的时候一个有趣的插曲是:当我读到Linkedin的案例那一段时,看到了一张关于Linkedin的插图:</p>
<p><img alt="linkedin" src="/static/2015/08/linkedin.jpg"></p>
<p>于是有了如下有意思的对话:</p>
<p><img alt="chat" src="/static/2015/08/chat.jpg"></p>
<p>书中还有多处提及到熟悉的前盛大创新院同事的名字和他们创业或参与创业的项目,加之本书正应了我自己当前创业所面临的用户增长的景,这些凑一起或许就是本书带给我的特别的亲近感吧!</p>从MANI理发店看公司的基因2015-08-05T10:00:00+08:002015-08-05T10:00:00+08:00飞龙tag:feilong.me,2015-08-05:/2015/08/mani-company-gene.html<p><img alt="gene" src="/static/2015/08/gene.jpg"></p>
<p>我家附近有一家韩国老板开的MANI理发店,此前有两位美发师A、B给我理过发,他们虽各有千秋,但个个技艺精湛,能把我这个头发越来越少的“面窝”头拾掇得有点模样,对比附近永琪的总监、首席理的则无法见人,所以近一年来我都是在这家店理的发。</p>
<p><img alt="mani" src="/static/2015/08/mani.jpg"></p>
<p>今年春节过后我又一次去这家店理发,发现这两位美发师不见了,据说开店的开店、回家的回家,各奔自己的前程去了,无奈之下我只好找了店里的另一位美发师C来理,因为C之前没有跟我理过发,加上我捉急的头发,C和老板就我的头发应该怎么理商量了半天才开剪,结果理出来的效果非常一般,跟之前两位理的相去甚远,我对此店的印象一下子跌到了谷底,就差给差评。这次理完发之后,因为一直耿耿于怀C理的不好,在MANI和永琪摇摆纠结了很久,我拖延了近2个月才不得不去理发,最后抱着再试试看的心态,硬着头皮还是去了MANI,刚进去就发现一张新面孔发型师D(C已经不见了),要不就他吧我想,在跟他抱怨说上次的C理的不好后,D也找来店长一块商量要怎么剪好,结果这次剪的几乎跟之前的两位美发师剪的一样棒,我又找回了从前来这家店的感觉,至今我每次都是来MANI找D理发。</p>
<p>高兴之余我就观察琢磨,发现MANI的一些特别之处:</p>
<ul>
<li>老板亲自督导发型设计</li>
<li>所有的美发师包括老板都会亲自给顾客洗头,不像永琪等洗头交给洗头小工。</li>
<li>慢工出细活,每次理发时间均超过20分钟</li>
</ul>
<p>“老板要求非常严,技术不过硬的根本入不了他法眼。两位美发师走之后,我们招了很久,终于招到这位D …</p><p><img alt="gene" src="/static/2015/08/gene.jpg"></p>
<p>我家附近有一家韩国老板开的MANI理发店,此前有两位美发师A、B给我理过发,他们虽各有千秋,但个个技艺精湛,能把我这个头发越来越少的“面窝”头拾掇得有点模样,对比附近永琪的总监、首席理的则无法见人,所以近一年来我都是在这家店理的发。</p>
<p><img alt="mani" src="/static/2015/08/mani.jpg"></p>
<p>今年春节过后我又一次去这家店理发,发现这两位美发师不见了,据说开店的开店、回家的回家,各奔自己的前程去了,无奈之下我只好找了店里的另一位美发师C来理,因为C之前没有跟我理过发,加上我捉急的头发,C和老板就我的头发应该怎么理商量了半天才开剪,结果理出来的效果非常一般,跟之前两位理的相去甚远,我对此店的印象一下子跌到了谷底,就差给差评。这次理完发之后,因为一直耿耿于怀C理的不好,在MANI和永琪摇摆纠结了很久,我拖延了近2个月才不得不去理发,最后抱着再试试看的心态,硬着头皮还是去了MANI,刚进去就发现一张新面孔发型师D(C已经不见了),要不就他吧我想,在跟他抱怨说上次的C理的不好后,D也找来店长一块商量要怎么剪好,结果这次剪的几乎跟之前的两位美发师剪的一样棒,我又找回了从前来这家店的感觉,至今我每次都是来MANI找D理发。</p>
<p>高兴之余我就观察琢磨,发现MANI的一些特别之处:</p>
<ul>
<li>老板亲自督导发型设计</li>
<li>所有的美发师包括老板都会亲自给顾客洗头,不像永琪等洗头交给洗头小工。</li>
<li>慢工出细活,每次理发时间均超过20分钟</li>
</ul>
<p>“老板要求非常严,技术不过硬的根本入不了他法眼。两位美发师走之后,我们招了很久,终于招到这位D”,老板娘曾说道。或许这些点加一起就是MANI理发店的基因,虽然MANI中间出现了短暂的人员真空,但MANI不因高手A、B的离开的而改变,MANI还是那家MANI。</p>
<p>公司高管离职的案例时有耳闻,华为不会因为曾有接班人一说的李一男的离开而不是华为、360不会因为傅盛离开而不是360、Google不会因为Marissa Mayer去了Yahoo就不是Google。有趣的是,Marissa Mayer去了Yahoo当CEO,Yahoo还是Yahoo而不是Google。</p>
<p>从MANI理发店的案例中我学到:当一个公司的文化基因已经形成的时候,单个核心人物的离开会给公司造成阵痛,但是公司的基因不会轻易被改变,我自己的创业公司又何尝不是如此。</p>追求而不苛求完美2015-08-03T10:00:00+08:002015-08-03T10:00:00+08:00飞龙tag:feilong.me,2015-08-03:/2015/08/why-do-perfect.html<p><img alt="perfect" src="/static/2015/08/perfect.jpg"></p>
<p>在上篇<a href="/2015/07/you-can-do-better">你可以做得更好</a>中我提到要“追求卓越,做到更好”,但是没有说“做到最好或追求完美”,一旦这么说就必须得说另半句即“不要苛求完美”了。作为一名移动互联网创业狗,对此我就从创业公司开发一款产品的角度来说起。</p>
<p>首先,我们要追求完美。当今正处于一个全民创业的浪潮时代,除了BAT等互联网大鳄外,创业公司千千万,每个创业公司面临的市场竞争空前激烈,你所见的几乎任何产品方向均有人在尝试或即将加入战团,这还不包括可能的部分产品已成先烈。特别对于移动互联网,现在App Store和Google Play上统计的APP数量分别在恐怖的150万和160万左右,这是一个APP泛滥的时代,也是一个越来越崇尚用户体验的时代,很多人的手机里都充斥着大量鸡肋的低频、超低频甚至从未打开的APP。如果公司和团队成员没有以严肃认真一丝不苟的工作态度来做事、没有以追求完美的心态来做产品,把产品细节打磨做到位,你很难从这激烈的竞争中胜出。</p>
<p>但是,追求完美到完美主义的程度通常会导致拖延和拖延症:</p>
<ul>
<li>
<p>对事而言,如果说把一件事做完要1.0的工作量的话,那么要把它做到更好要1.2至2.0的工作量,但是要做到完美可能10甚至是100倍的付出都达不到。工作量的增加,在互联网行业最常见的解决办法就是加班(996你懂的),当工作量增加到加班都完成不了的情况下,就必然导致了拖延。当今成功的个体开发者已越来越少见,开发一款产品幕后更多的是一个公司、一个团队,需要每一个角色 …</p></li></ul><p><img alt="perfect" src="/static/2015/08/perfect.jpg"></p>
<p>在上篇<a href="/2015/07/you-can-do-better">你可以做得更好</a>中我提到要“追求卓越,做到更好”,但是没有说“做到最好或追求完美”,一旦这么说就必须得说另半句即“不要苛求完美”了。作为一名移动互联网创业狗,对此我就从创业公司开发一款产品的角度来说起。</p>
<p>首先,我们要追求完美。当今正处于一个全民创业的浪潮时代,除了BAT等互联网大鳄外,创业公司千千万,每个创业公司面临的市场竞争空前激烈,你所见的几乎任何产品方向均有人在尝试或即将加入战团,这还不包括可能的部分产品已成先烈。特别对于移动互联网,现在App Store和Google Play上统计的APP数量分别在恐怖的150万和160万左右,这是一个APP泛滥的时代,也是一个越来越崇尚用户体验的时代,很多人的手机里都充斥着大量鸡肋的低频、超低频甚至从未打开的APP。如果公司和团队成员没有以严肃认真一丝不苟的工作态度来做事、没有以追求完美的心态来做产品,把产品细节打磨做到位,你很难从这激烈的竞争中胜出。</p>
<p>但是,追求完美到完美主义的程度通常会导致拖延和拖延症:</p>
<ul>
<li>
<p>对事而言,如果说把一件事做完要1.0的工作量的话,那么要把它做到更好要1.2至2.0的工作量,但是要做到完美可能10甚至是100倍的付出都达不到。工作量的增加,在互联网行业最常见的解决办法就是加班(996你懂的),当工作量增加到加班都完成不了的情况下,就必然导致了拖延。当今成功的个体开发者已越来越少见,开发一款产品幕后更多的是一个公司、一个团队,需要每一个角色、每一人员分工协作,工作流水环环相扣,一个人的拖延就会掣肘他人的工作,影响整个团队的进度,最终导致整个产品交付的延期。在市场行为下,产品的交付时间点是很难改变的,延期即意味着巨大的损失。</p>
</li>
<li>
<p>对人而言,等万事俱备才动工的、不分大小主次都要追求完美从而无从下手的、做任何事情前必须全部清理一下前面的事情的这种种完美主义者,通常就是一名拖延症患者。
所以,我们不能苛求完美。在长远目标追求完美的框架基础下,容许和接受一定条件下的“不完美”。对于创业公司而言,人力、物力、财力、时间等各方面资源都非常有限,没有好的设计师,界面美观就不能苛求;没有好的iOS开发人员,iOS版本就不能苛求;没有安卓开发人员,别说苛求,短期内甚至必须放弃安卓版本;即使有最优秀的设计师,也不能苛求所有的设计一次性到位,不然必会分不清轻重而顾此失彼。完美和进度之间必须做适当的平衡和取舍,容许一定条件的“不完美”,以达到当前的最优。</p>
</li>
</ul>
<p>对于一时的“不完美”,我们可以通过小步快跑、持续改进的方式来趋于完美。现在比较推崇精益创业(可参阅同名书),其核心思路是:先在市场中投入一个极简的最小可行化产品MVP(Minimum Viable Product),然后通过不断的学习和有价值的用户反馈,对产品进行快速迭代优化,以期适应市场和应对市场的快速变化。每一个迭代周期都很短暂,对于移动互联网产品而言,通常在2-4周之间,如此短的时间内很多事情不可能做到完美,但是我们可以抓住每次迭代的核心,把最重要的部分尽量做好。通过这种持续改进的方式,能够快速的向正确的目标迈进,进而将产品逐步推向完美。容许一时的“不完美”是为更好、更快的趋于完美。</p>
<p>类比系统的开发一款产品,即使小如设计一个ICON,其道理也一样的,只不过整个周期/迭代周期要短的多:</p>
<ol>
<li>选型:ICON用什么形象来体现?</li>
<li>草案:根据选定的备选形象画初步的草案;</li>
<li>初案:根据筛选出的备选草案做初步的ICON设计;</li>
<li>详案:对确定的一个初案做最终的细节完善,调色、对齐、整体一致性等等,此步会产出多个有细节差异的备选详案,供做最终选择;</li>
<li>迭代:版本UI调整,1-4步的全部或部分步骤会需要做多次迭代。</li>
</ol>
<p>我们不可能苛求1、2、3步就拿出完美的ICON,如果一次到位了更多的会是根不是最终要的,第4步也需要经过多次细节调整后,才可以逐步完善此ICON。而一个ICON的设计只是一次产品迭代周期中的一个小点,还有更多的其他的设计工作要在迭代周期内交付,此ICON能不能做到完美,还依赖于和影响到其它设计工作能否做到完美。本次产品迭代交付的此ICON有可能完美,更可能还“不完美”,甚至还不知道完美的此ICON应该是什么样!</p>
<p>“It's better to be quick than brilliant.”,Paul Buchheit 的这句话中文意即“唯快不破”,容许和接受一定条件下的“不完美”,快速原型(MVP)、快速迭代、快速改进,方可以快速的趋于完美。</p>
<hr>
<p>题图来自网络:By 胖兔子粥粥</p>你可以做得更好2015-07-23T10:00:00+08:002015-07-23T10:00:00+08:00飞龙tag:feilong.me,2015-07-23:/2015/07/you-can-do-better.html<p><img alt="do better" src="/static/2015/07/do-better.jpg"></p>
<p>前几天看到一位设计师朋友发的一张图:</p>
<p><img alt="draft" src="/static/2015/07/draft.jpg"></p>
<p>我当时就震惊了,TA为了一项设计折腾了好几天,做了16稿,我不知道后面是不是还有draft17、draft18、draft19……。这需要挖空心思绞尽脑汁,其心力的付出不是简单的1<em>16而是1</em>16*10。虽然TA现在还只是一名初级设计师,但有此精益求精、追求卓越的精神并能持之以恒的话,必有所成。</p>
<p>日常工作中有太多的你可以做得更好的点:</p>
<ul>
<li>一个变量名、方法名、类名、数据库字段名是否有更好的词?</li>
<li>一段代码是否可以优化的更健壮、可维护、性能更好?</li>
<li>一句文案是否可以改的让用户感到更温暖?</li>
<li>一个ICON是否能够更好的传递使用场合所要表达的意思?</li>
<li>甚至你的办公桌面和电脑桌面是不是可以整理的更整洁?</li>
</ul>
<p>要做完一件事容易,但做好一件事情难,而这之间的差别往往只在你一念之间:“你,有没有去认真推敲,并想办法做出改善”。</p>
<p>其实,你可以做得更好。</p><p><img alt="do better" src="/static/2015/07/do-better.jpg"></p>
<p>前几天看到一位设计师朋友发的一张图:</p>
<p><img alt="draft" src="/static/2015/07/draft.jpg"></p>
<p>我当时就震惊了,TA为了一项设计折腾了好几天,做了16稿,我不知道后面是不是还有draft17、draft18、draft19……。这需要挖空心思绞尽脑汁,其心力的付出不是简单的1<em>16而是1</em>16*10。虽然TA现在还只是一名初级设计师,但有此精益求精、追求卓越的精神并能持之以恒的话,必有所成。</p>
<p>日常工作中有太多的你可以做得更好的点:</p>
<ul>
<li>一个变量名、方法名、类名、数据库字段名是否有更好的词?</li>
<li>一段代码是否可以优化的更健壮、可维护、性能更好?</li>
<li>一句文案是否可以改的让用户感到更温暖?</li>
<li>一个ICON是否能够更好的传递使用场合所要表达的意思?</li>
<li>甚至你的办公桌面和电脑桌面是不是可以整理的更整洁?</li>
</ul>
<p>要做完一件事容易,但做好一件事情难,而这之间的差别往往只在你一念之间:“你,有没有去认真推敲,并想办法做出改善”。</p>
<p>其实,你可以做得更好。</p>我为什么要用八卦(挂)做头像2015-07-22T10:00:00+08:002015-07-22T10:00:00+08:00飞龙tag:feilong.me,2015-07-22:/2015/07/why-use-bagua-avatar.html<p><img alt="bagua" src="/static/2015/07/bagua.jpg"></p>
<h4>首先,当然是《易经》八卦而不是娱乐八卦。</h4>
<p>个人比较偏好中国传统古圣先贤的一些著作,《易经》是我最喜欢的著作之一(虽然至今没有读懂几卦)。《易经》乾卦九五爻“飞龙在天,利见大人”可以说是易经里最吉的一爻,通常说的九五之尊也来于此爻,再上一爻的上九就是大家熟知的“亢龙有悔”。我用的网名飞龙也来源于此,不过我的网名全称是“飞龙非龙”,我不是飞龙而是非龙,也正是因为非龙,所以时时告诫自己要有颗谦卑的心,努力奋斗以有朝一日能接近或达到飞龙在天的境界。吴军博士的《文明之光》中有讲到当年莱布尼兹是受《易经》启发而发明二进制的,而二进制正是我目前从事的软件/计算机行业技术的核心理论基础,从这个角度来讲,这也算是爱屋及乌吧!</p>
<h4>其次,卦者挂也。</h4>
<p><img alt="guake" src="/static/2015/07/guake.jpg"></p>
<p>卦象就是挂起来看的大像,八卦-->八挂,我读大学有创记录的八挂经历,大一大二我没有挂过一门课,但是大三一年时间我就挂了八科,也正因为这八挂,我入武汉大学宝室而空手归,读的物理只勉勉强强拿到了一张毕业证,学位证至今还躺在学校的某个柜子里不属于我,用“八挂”做头像多少有点自嘲的意思。而这为人所不齿的八挂经历,我并不后悔,相反倒有些莫名的庆幸 …</p><p><img alt="bagua" src="/static/2015/07/bagua.jpg"></p>
<h4>首先,当然是《易经》八卦而不是娱乐八卦。</h4>
<p>个人比较偏好中国传统古圣先贤的一些著作,《易经》是我最喜欢的著作之一(虽然至今没有读懂几卦)。《易经》乾卦九五爻“飞龙在天,利见大人”可以说是易经里最吉的一爻,通常说的九五之尊也来于此爻,再上一爻的上九就是大家熟知的“亢龙有悔”。我用的网名飞龙也来源于此,不过我的网名全称是“飞龙非龙”,我不是飞龙而是非龙,也正是因为非龙,所以时时告诫自己要有颗谦卑的心,努力奋斗以有朝一日能接近或达到飞龙在天的境界。吴军博士的《文明之光》中有讲到当年莱布尼兹是受《易经》启发而发明二进制的,而二进制正是我目前从事的软件/计算机行业技术的核心理论基础,从这个角度来讲,这也算是爱屋及乌吧!</p>
<h4>其次,卦者挂也。</h4>
<p><img alt="guake" src="/static/2015/07/guake.jpg"></p>
<p>卦象就是挂起来看的大像,八卦-->八挂,我读大学有创记录的八挂经历,大一大二我没有挂过一门课,但是大三一年时间我就挂了八科,也正因为这八挂,我入武汉大学宝室而空手归,读的物理只勉勉强强拿到了一张毕业证,学位证至今还躺在学校的某个柜子里不属于我,用“八挂”做头像多少有点自嘲的意思。而这为人所不齿的八挂经历,我并不后悔,相反倒有些莫名的庆幸。如果不是这八挂我可能一路硕博甚至博士后,现在呆在一个研究所里从事我并不喜欢的物理研究工作;如果不是这八挂,我不会经历数年无比痛苦的择业迷茫,我也就不会如此珍惜后来得之不易的软件行业从业机会,也就不会有今日的移动互联网创业;如果不是这八挂,我可能还搞不清应该“干一行,爱一行”还是“爱一行,干一行”;如果不是这八挂,我也不会进而鼓励一些朋友们放下自己所学的专业,去追求内心最真实的兴趣爱好;如果不是这八挂,我在用人的时候可能已错过了很多优秀的人才,比如目前我团队里学音乐的安卓开发程序员。</p>
<p>有意思的是,朋友圈今天刷屏的一个关于大神道哥的帖子里透露道哥学的化学没拿到学位,我学的物理也没拿到学位,咱们都是兴趣发生转移到软件上了的活例子。</p>
<p>所以,我用八卦(挂)做头像,以提醒自己不忘以往所犯的过失、不忘初心努力追求自己的兴趣和梦想;也提醒自己不拘一格降人才,不要错过各种挂但优秀的人才。</p>飞龙札记微信公共账号开篇2015-07-21T10:00:00+08:002017-03-03T16:20:00+08:00飞龙tag:feilong.me,2015-07-21:/2015/07/write-in-offical-account.html<p>曾经我的技术博客 <a href="http://feilong.me">http://feilong.me</a>记录了我在学习和使用Python(特别是Tornado框架)中的一些经验点滴,没想到直到今日我在一个Python QQ群里开口的时候,仍有Python爱好者在群里说学Tornado的时候是看着我的博客文章成长起来的,很欣慰我的博客曾经帮助过一些人。</p>
<p>有愧于近两年来在技术领域没有什么进展,所以此博客已长草。实际上在我的工作、生活、读书过程中其实有不少东西可记的,而碍于我从小自负自己聪明绝顶(现在真达成了)从不记录笔记,加之狗屎一样的记忆力,结果读过的书白读了、看过的电影白看了、工作遇到的教训白经历了,有鉴于于此,有必要再找一个地方来记录这些,微信公共账号这里或许是一个不错的地方,那就从现在开始吧!</p>
<p>2017/03/03更新:在微信公共账号上写文章我的一次尝试,在看到陈浩<a href="http://coolshell.cn/articles/17391.html">为什么我不在微信公众号上写文章</a>之后,我很认同他这篇文章的观点,自那以后我不再在公共账号上写了(给自己找了个不写文章的好理由)。</p><p>曾经我的技术博客 <a href="http://feilong.me">http://feilong.me</a>记录了我在学习和使用Python(特别是Tornado框架)中的一些经验点滴,没想到直到今日我在一个Python QQ群里开口的时候,仍有Python爱好者在群里说学Tornado的时候是看着我的博客文章成长起来的,很欣慰我的博客曾经帮助过一些人。</p>
<p>有愧于近两年来在技术领域没有什么进展,所以此博客已长草。实际上在我的工作、生活、读书过程中其实有不少东西可记的,而碍于我从小自负自己聪明绝顶(现在真达成了)从不记录笔记,加之狗屎一样的记忆力,结果读过的书白读了、看过的电影白看了、工作遇到的教训白经历了,有鉴于于此,有必要再找一个地方来记录这些,微信公共账号这里或许是一个不错的地方,那就从现在开始吧!</p>
<p>2017/03/03更新:在微信公共账号上写文章我的一次尝试,在看到陈浩<a href="http://coolshell.cn/articles/17391.html">为什么我不在微信公众号上写文章</a>之后,我很认同他这篇文章的观点,自那以后我不再在公共账号上写了(给自己找了个不写文章的好理由)。</p>我玩游戏这些年,无基友,不游戏2014-08-02T18:15:00+08:002014-08-02T18:15:00+08:00飞龙tag:feilong.me,2014-08-02:/2014/08/no-gyou-no-game.html<p>1999年的五一长假,我在寝室基友的的怂恿下开始玩星际争霸,从此一发不可收拾,与游戏结下了不解之缘,其实怨也是有的,事见<a class="reference external" href="http://feilong.me/pages/about">关于飞龙</a>。</p>
<p>99年那时才刚刚有了校园网络,外网带宽非常有限,大家更多的是在局域网内玩,而那时最适合局域网内玩的游戏莫过于星际争霸了。星际虽然也可以单机玩,但更多的是局域网内联机对战,也就是和基友一起玩,我印象最深的游戏ID有ych、coda、111、Phoenix、savage、Joker等,这些人除了是游戏中的基友之外也渐渐成了线下的好基友,大家没事就一起高谈阔论星际的各种战略、战术问题、还有大家一起玩的战例。我记得有一次我作为观战(ob)看了一整晚coda
vs savage,这也成为我们三基友之间长期会聊到的一个话题。</p>
<p><img alt="image0" class="aligncenter" src="/static/2014/08/starcraft-300x225.jpg" style="width: 300px; height: 225px;" /></p>
<p>01年我大学毕业,这些基友四散到各地,不再在一个局域网了,再也不能一起愉快的游戏了,我转而去回顾一些经典单机游戏,如英雄无敌、暗黑、博德之门、冰风谷、辐射、异域镇魂曲等(有些可联网但当单机在玩),但这些游戏大多一年玩一遍就会觉得很无聊,关键在于单机没有基友一起玩,游戏的乐趣大打折扣。在这极度无聊的时刻,浩方对战平台横空出世了,在互联网上架起了一个虚拟的局域网让广大基友可以一起愉快的玩耍星际争霸、魔兽争霸、英雄无敌等 …</p><p>1999年的五一长假,我在寝室基友的的怂恿下开始玩星际争霸,从此一发不可收拾,与游戏结下了不解之缘,其实怨也是有的,事见<a class="reference external" href="http://feilong.me/pages/about">关于飞龙</a>。</p>
<p>99年那时才刚刚有了校园网络,外网带宽非常有限,大家更多的是在局域网内玩,而那时最适合局域网内玩的游戏莫过于星际争霸了。星际虽然也可以单机玩,但更多的是局域网内联机对战,也就是和基友一起玩,我印象最深的游戏ID有ych、coda、111、Phoenix、savage、Joker等,这些人除了是游戏中的基友之外也渐渐成了线下的好基友,大家没事就一起高谈阔论星际的各种战略、战术问题、还有大家一起玩的战例。我记得有一次我作为观战(ob)看了一整晚coda
vs savage,这也成为我们三基友之间长期会聊到的一个话题。</p>
<p><img alt="image0" class="aligncenter" src="/static/2014/08/starcraft-300x225.jpg" style="width: 300px; height: 225px;" /></p>
<p>01年我大学毕业,这些基友四散到各地,不再在一个局域网了,再也不能一起愉快的游戏了,我转而去回顾一些经典单机游戏,如英雄无敌、暗黑、博德之门、冰风谷、辐射、异域镇魂曲等(有些可联网但当单机在玩),但这些游戏大多一年玩一遍就会觉得很无聊,关键在于单机没有基友一起玩,游戏的乐趣大打折扣。在这极度无聊的时刻,浩方对战平台横空出世了,在互联网上架起了一个虚拟的局域网让广大基友可以一起愉快的玩耍星际争霸、魔兽争霸、英雄无敌等,03年开始我又在浩方平台上玩起了星际,也正是这时我加入了一个叫MecurY的星际小战队,和战队的一帮基友长期出没在星际的1.08高手大厅,这个战队的QQ群我一直还在,虽然群已经不活跃了,但偶尔看到好基友的QQ或微信的动态大家都还会互动一下,基情永在。</p>
<p><img alt="image1" class="size-full wp-image-852 aligncenter" src="/static/2014/08/haofang.jpg" style="width: 160px; height: 150px;" /></p>
<p>05年我因为多方的原因,戒了游戏,一直到2012年暗黑3出来,这段时间都没有去碰过游戏,所以很遗憾的我错过了魔兽世界,一个重度依赖于基友一起玩的游戏,深以为憾。</p>
<p>2012年暴雪在暗黑2的十来年之后终于放出了暗黑3,因为之前有强烈的暗黑系列情节,再加上当时有好几个同事在中午午休的时候会耍上两把,最终禁不住基友的诱惑,我重新掉游戏坑里了(这次还花了美刀买账号,坑)。暗黑3出来以后,虽然销量创纪录,但是吐槽如潮,很快陆陆续续同事也都不玩了,没了身边的基友我只好去逛网易的暗黑3论坛找找有没有好基友,这个论坛当时很活跃,每天的帖子量也很大,我几乎每天都上,但是在我玩暗黑3的近一年时间里,我只在这论坛上结识了一个游戏中的基友,奇哉怪也。后来没有了基友,我仍然玩了差不多半年的时间暗黑,也算是一件奇葩事,估计是跟我当时mbp上就这么一个游戏有关,虽然很无聊但是没有别的玩:(</p>
<p><img alt="image2" class="size-medium wp-image-854 aligncenter" src="/static/2014/08/diablo3-300x170.jpg" style="width: 300px; height: 170px;" /></p>
<p>2013年的6月,又是被基友同事给坑了,开始玩手游(顺便扔了暗黑3),就是前一篇博客里提到的四国战记(很小众的游戏),几个好基友天天讨论卡牌、符文、卡组、关卡等等。在四国的魔神出了之后,因为它特耗时且无聊,所以自己写了个小外挂自动去打魔神,有兴趣的详见<a class="reference external" href="http://feilong.me/2013/08/siguozhanji-boss-fight-robot">四国战记外挂</a>,这个外挂非常好用,所以陆陆续续就有游戏中的玩家来找我要用这个挂,我后续也开发了不少新的功能,直到有一天功能齐备了,还让基友瓜皮同学放淘宝上开卖了。因为这个外挂,我们把四国战记国服的最活跃的一批玩家全圈到了外挂群,大家成了好基友,包括瓜皮、F、老夫、老君、活胖、苔二、牛头、校长、秀秀、凯托、阿瓦、小可爱、傲气、弑神等等。不止一次有四国玩家提到,要不是因为这个挂群拉近了这帮玩家,他们早就不玩四国战记了,而实际上在线下我也已见过瓜皮、F、老君、牛头、傲气、弑神等几个,分别是在广州、杭州见到他们的,而且我去都是好吃好喝好招待,我们在线下初见时完全不是陌生人见面,而是一副多年老友的感觉,这不得不惊叹于游戏基友的力量。</p>
<p><img alt="image3" class="size-medium wp-image-855 aligncenter" src="/static/2014/08/sgzj-300x200.jpg" style="width: 300px; height: 200px;" /></p>
<p>回顾我玩游戏这些年,无基友,不游戏,玩游戏因为有了这些基友而更精彩。</p>
四国战记外挂(四国助手)2013-08-14T23:50:00+08:002013-08-14T23:50:00+08:00飞龙tag:feilong.me,2013-08-14:/2013/08/siguozhanji-boss-fight-robot.html<p><a class="reference external" href="http://sgzj.muhegame.com/">四国战记</a>是我最近玩过的比较不错的一款卡牌手游,玩四国依稀有点当年大学时代玩英雄无敌的感觉,我先无节操的推荐一下这款手游,邀请码就不放了,以免纯广告之嫌,我的号二区水源精华“灰太龙”,有兴趣的可以游戏里来找我(目测四国GM第一个来找我了,杯具鸟)。</p>
<p>2013/08/31更新:
我开发的外挂已实现自动打魔神、CD一到自动找合适的贼打、自动送和获取好友给的行动力、自动刷塔等辅助功能。</p>
<p>2014/02/07更新: 目前功能已非常齐全,且已正式对外服务,请见:
<a class="reference external" href="%20http://sgzj.shouyouqu.com/">四国助手</a>
<a class="reference external" href="%20http://sgzj.shouyouqu.com/">http://sgzj.shouyouqu.com/</a>
和对应的<a class="reference external" href="http://cc2046.taobao.com/index.htm">淘宝店</a>
<a class="reference external" href="http://cc2046.taobao.com/index.htm">http://cc2046.taobao.com/index.htm</a></p>
<div class="section" id="id2">
<h2>挂机起因</h2>
<p>玩四国的除了大RMB玩家外可能都比较缺钱强化卡牌,而游戏里面一个重要的来钱手段就是7月18号开启的魔神战,全服务器的玩家共同砍魔神获得金币或者卡牌奖励,魔神战每天下午1点和晚9点开始持续2小时(除非魔神提前被砍死),打魔神战有个要命的CD(俗称冷却时间),CD根据卡组的COST值有些微小差异,COST越低CD越短,但最少差不多也要1分钟,也就是说为了获得较高的金币奖励,玩家不得不开着四国 …</p></div><p><a class="reference external" href="http://sgzj.muhegame.com/">四国战记</a>是我最近玩过的比较不错的一款卡牌手游,玩四国依稀有点当年大学时代玩英雄无敌的感觉,我先无节操的推荐一下这款手游,邀请码就不放了,以免纯广告之嫌,我的号二区水源精华“灰太龙”,有兴趣的可以游戏里来找我(目测四国GM第一个来找我了,杯具鸟)。</p>
<p>2013/08/31更新:
我开发的外挂已实现自动打魔神、CD一到自动找合适的贼打、自动送和获取好友给的行动力、自动刷塔等辅助功能。</p>
<p>2014/02/07更新: 目前功能已非常齐全,且已正式对外服务,请见:
<a class="reference external" href="%20http://sgzj.shouyouqu.com/">四国助手</a>
<a class="reference external" href="%20http://sgzj.shouyouqu.com/">http://sgzj.shouyouqu.com/</a>
和对应的<a class="reference external" href="http://cc2046.taobao.com/index.htm">淘宝店</a>
<a class="reference external" href="http://cc2046.taobao.com/index.htm">http://cc2046.taobao.com/index.htm</a></p>
<div class="section" id="id2">
<h2>挂机起因</h2>
<p>玩四国的除了大RMB玩家外可能都比较缺钱强化卡牌,而游戏里面一个重要的来钱手段就是7月18号开启的魔神战,全服务器的玩家共同砍魔神获得金币或者卡牌奖励,魔神战每天下午1点和晚9点开始持续2小时(除非魔神提前被砍死),打魔神战有个要命的CD(俗称冷却时间),CD根据卡组的COST值有些微小差异,COST越低CD越短,但最少差不多也要1分钟,也就是说为了获得较高的金币奖励,玩家不得不开着四国,魔神CD一到马上开砍,不得不说这招对提高游戏日活和用户停留时间应该是帮助蛮大的。而作为一名懒人的我,没有那个精力也没有那个时间盯着手机砍魔神,于是就琢磨是否可以写个机器人挂机砍魔神,事实证明这完全是可以的,因为四国是基于HTTP的且没有用HTTPS。</p>
</div>
<div class="section" id="id3">
<h2>挂机程序</h2>
<p>挂机程序原理很简单,只需要抓包抓到魔神战的HTTP请求URL地址和用户的Cookie,再在魔神战这个时间点启动程序模拟砍魔神的HTTP请求即可。最简单的其实用CURL就可以实现这个功能,不过为了测试并发和加入一些随机因子让机器人更像真人在玩,我后来用Python写了个简单的程序来做这件事。处于xxx考虑,这里我暂且把部分代码用xxx替代,Python代码如下:</p>
<div class="highlight"><pre><span></span><span class="c1"># -*- coding: utf-8 -*-</span>
<span class="c1">#</span>
<span class="c1"># @author: Felinx Lee</span>
<span class="c1"># Created on Jul 24, 2013</span>
<span class="c1">#</span>
<span class="c1"># 四国战记刷魔神boss</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
<span class="kn">from</span> <span class="nn">pytz</span> <span class="kn">import</span> <span class="n">timezone</span>
<span class="kn">from</span> <span class="nn">tornado.httpclient</span> <span class="kn">import</span> <span class="n">HTTPClient</span><span class="p">,</span> <span class="n">HTTPRequest</span>
<span class="kn">from</span> <span class="nn">tornado</span> <span class="kn">import</span> <span class="n">escape</span>
<span class="n">max_threads</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># 大于1时会用多线程同时砍,事实证明四国战记服务器程序还是蛮靠谱的,多线程并发会放进队列,不能同时砍两次甚至更多次:)</span>
<span class="n">url_suffix</span> <span class="o">=</span> <span class="s2">"siguozhanji.muhenet.com/boss.php?do=Figxxxxxxxxxxxxxxxxxxxxxx"</span>
<span class="n">users</span> <span class="o">=</span> <span class="p">(</span>
<span class="p">{</span><span class="s2">"server"</span><span class="p">:</span> <span class="s2">"s2"</span><span class="p">,</span> <span class="s2">"cookie"</span><span class="p">:</span> <span class="s2">"_sid=cookiexxxxxx1"</span><span class="p">},</span> <span class="c1"># s2 表 2 区</span>
<span class="p">{</span><span class="s2">"server"</span><span class="p">:</span> <span class="s2">"s3"</span><span class="p">,</span> <span class="s2">"cookie"</span><span class="p">:</span> <span class="s2">"_sid=cookiexxxxxx2"</span><span class="p">},</span> <span class="c1"># s2 表 3 区</span>
<span class="p">)</span>
<span class="n">log</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)),</span> <span class="s2">"sg_boss.log"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">fight</span><span class="p">(</span><span class="n">user</span><span class="p">):</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">())</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">HTTPClient</span><span class="p">()</span>
<span class="n">url</span> <span class="o">=</span> <span class="s2">"http://</span><span class="si">%s</span><span class="s2">.</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">user</span><span class="p">[</span><span class="s2">"server"</span><span class="p">],</span> <span class="n">url_suffix</span><span class="p">)</span>
<span class="n">request</span> <span class="o">=</span> <span class="n">HTTPRequest</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">"Cookie"</span><span class="p">:</span> <span class="n">user</span><span class="p">[</span><span class="s2">"cookie"</span><span class="p">]})</span>
<span class="n">respone</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">fetch</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">escape</span><span class="o">.</span><span class="n">json_decode</span><span class="p">(</span><span class="n">respone</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">log</span><span class="p">,</span> <span class="s2">"a+"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">tz</span> <span class="o">=</span> <span class="n">timezone</span><span class="p">(</span><span class="s2">"Asia/Shanghai"</span><span class="p">)</span> <span class="c1"># 因为我的服务器在美国,用的是UTC标准时间,这里为了日志记录方便转成了北京时间</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">(</span><span class="n">tz</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">"%Y-%m-</span><span class="si">%d</span><span class="s2"> </span><span class="si">%X</span><span class="s2">"</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="s2">"</span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">r</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"message"</span><span class="p">,</span> <span class="s2">"OK"</span><span class="p">),</span> <span class="n">r</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">escape</span><span class="o">.</span><span class="n">utf8</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">40</span><span class="p">):</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> <span class="c1"># 1.5 avg + 0.5</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">max_threads</span><span class="p">):</span>
<span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">users</span><span class="p">:</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">fight</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">user</span><span class="p">,))</span>
<span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</pre></div>
<p>然后在系统的crontab里添加如下这样的一段定时任务,让程序到点自动运行</p>
<pre class="literal-block">
* 5 * * * python /home/felinx/temp/sg_boss_bot.py
0-30 6 * * * python /home/felinx/temp/sg_boss_bot.py
* 13 * * * python /home/felinx/temp/sg_boss_bot.py
0-30 14 * * * python /home/felinx/temp/sg_boss_bot.py
</pre>
<p>注意上面的小时即每行的第二个参数是UTC时间的小时,加8就是北京时间,分别对应到13、14、21、22点,0-30指只前半小时生效,因为通常一个小时以后魔神就被那些大神玩家砍死了......</p>
<div class="line-block">
<div class="line">比较有意思的是如果机器人帮你砍过了,如果手机上的四国战记是开着的,它会自动切换到魔神战的打斗场景里去。</div>
<div class="line">除了魔神战,其它的事情比如自动刷塔、自动砍盗贼是不是也可以做到呢?原则上也是可以的:)</div>
</div>
</div>
<div class="section" id="id4">
<h2>挂机效果</h2>
<p>从7月24号我这个挂机机器人上线以来,我的号每次魔神战(基本都是3冰熊的卡组)大概可以砍10w上下的功勋值拿到24w+的游戏金币,有时候还能混到个强化牌加经验的可口食物,但不得不说有些大RMB玩家太疯狂,我的这机器人也砍的没有他们勤快和多分:)</p>
<p>不得不赞一下四国真是一个良心手游,值得推荐。我没有充过钱(四国团队的人要不喜欢了)依然可以玩的挺high,相比我叫MT我就怎么都玩不下去,而且自我第一天开始玩起到现在每天都在玩,现在每天固定要刷完5、6、7塔,有空时砍砍盗贼,当然魔神战没时间盯这就靠这机器人了,我加的那些好友大部分的等级都跟我同步在上升,四国的日活数据还是很不错的,祝贺四国战记团队。</p>
<p>最后,四国团队的人该有一天会发现我在挂机(我都写这了),把我的设备给封掉吧,然后就没有然后了...</p>
<p>附:写博客的这个时间机器人砍魔神的结果图</p>
<p><a class="reference external" href="/static/2013/08/IMG_1490.png"><img alt="image0" class="alignnone size-full wp-image-833" src="/static/2013/08/IMG_1490.png" style="width: 960px; height: 640px;" /></a></p>
</div>
实时消息处理系统NSQ & Python Worker2013-05-18T18:43:00+08:002013-05-18T18:43:00+08:00飞龙tag:feilong.me,2013-05-18:/2013/05/nsq-realtime-message-processing-system.html<p>NSQ是由知名短链接服务商<a class="reference external" href="https://bitly.com">bitly</a>用Go语言开发的实时消息处理系统,具有高性能、高可靠、无视单点故障等优点,是一个非常不错的新兴的消息队列解决方案。nsq现在发展很快,已有多种语言的客户端,Go和Python版本的客户端是官方出的,比较给力,其中Python客户端<a class="reference external" href="https://github.com/bitly/pynsq">pynsq</a>的Writer即发布消息部分的代码是我贡献的。</p>
<p>以下是我准备在5.22的上海GDG活动中做的有关NSQ的主题演讲的slideshare,看不到的同学请下载后面的pdf版本,关于nsq更详细的介绍就看我5.22日的主题分享了。</p>
<p>分享过程视频 <a class="reference external" href="http://video.tudou.com/v/XMjIyMjI3MDk5Ng==.html">NSQ & Python Worker视频</a></p>
<p>因为是支支用手机录的屏幕比较晃,大家凑合下。另外更正讲解过程中的一个口误,不是Go的作者之一follow了我的nsqworker项目而是nsq的主要作者。</p>
<p><a class="reference external" href="http://www.slideshare.net/FelinxLee/nsq-python-worker">Nsq & python
worker</a> from
<a class="reference external" href="http://www.slideshare.net/FelinxLee">Felinx Lee</a></p>
<p>PDF版本 <a class="reference external" href="/static/2013/05/NSQ-Python-Worker.pdf">NSQ-Python-Worker.pdf PDF</a></p>
<p>PPT提到的我写的nsqworker的项目地址见:<a class="reference external" href="https://github.com/felinx/nsqworker">https://github.com/felinx/nsqworker</a></p>
<p>NSQ是由知名短链接服务商<a class="reference external" href="https://bitly.com">bitly</a>用Go语言开发的实时消息处理系统,具有高性能、高可靠、无视单点故障等优点,是一个非常不错的新兴的消息队列解决方案。nsq现在发展很快,已有多种语言的客户端,Go和Python版本的客户端是官方出的,比较给力,其中Python客户端<a class="reference external" href="https://github.com/bitly/pynsq">pynsq</a>的Writer即发布消息部分的代码是我贡献的。</p>
<p>以下是我准备在5.22的上海GDG活动中做的有关NSQ的主题演讲的slideshare,看不到的同学请下载后面的pdf版本,关于nsq更详细的介绍就看我5.22日的主题分享了。</p>
<p>分享过程视频 <a class="reference external" href="http://video.tudou.com/v/XMjIyMjI3MDk5Ng==.html">NSQ & Python Worker视频</a></p>
<p>因为是支支用手机录的屏幕比较晃,大家凑合下。另外更正讲解过程中的一个口误,不是Go的作者之一follow了我的nsqworker项目而是nsq的主要作者。</p>
<p><a class="reference external" href="http://www.slideshare.net/FelinxLee/nsq-python-worker">Nsq & python
worker</a> from
<a class="reference external" href="http://www.slideshare.net/FelinxLee">Felinx Lee</a></p>
<p>PDF版本 <a class="reference external" href="/static/2013/05/NSQ-Python-Worker.pdf">NSQ-Python-Worker.pdf PDF</a></p>
<p>PPT提到的我写的nsqworker的项目地址见:<a class="reference external" href="https://github.com/felinx/nsqworker">https://github.com/felinx/nsqworker</a></p>
Web Performance & Load 测试工具multi-mechanize2013-02-19T19:21:00+08:002013-02-19T19:21:00+08:00飞龙tag:feilong.me,2013-02-19:/2013/02/load-testing-with-multi-mechanize.html<p>对Web服务做Performance & Load测试,最常见的工具有<a class="reference external" href="http://httpd.apache.org/docs/2.2/programs/ab.html">Apache
Benchmark</a>俗称ab和商用工具LoadRunner。ab简单直接,功能也相对较弱,但我们经常看到的对一些Web
server或者Framework的性能测试用的ab做的,而LoadRunner功能也确实很强大,各种大型软件公司、软件外包企业几乎是必备了,用起来很High,当然其价格也确实很High
:)</p>
<p>这里要介绍的<a class="reference external" href="https://github.com/cgoldberg/multi-mechanize">multi-mechanize(</a>这名忒难记)是一款用Python开发的Performance
&
Load测试工具,是由<a class="reference external" href="http://pylot.org/">Pylot</a>的作者新近开发的,算是升级换代的产品。用multi-mechanize可以通过编写Python脚本来实现较复杂的测试逻辑,其并发测试是通过multiprocessing(多进程)和多线程机制来实现的。</p>
<div class="section" id="id1">
<h2><strong>1. 安装</strong></h2>
</div>
<div class="section" id="pip-easy-install">
<h2>万能的pip&easy_install</h2>
</div>
<div class="section" id="pip-install-multi-mechanize-mechanize-numpy-matplotlib">
<h2>pip install multi-mechanize mechanize numpy matplotlib</h2>
<ul class="simple">
<li>mechanize是一个模拟browser行为的一个库,当然你也可以用其它的如urllib2、request、tornado.httpclient等等库,不是必须。</li>
<li>后面两个numpy和matplotlib也是可选的,当你需要它自动生成图形化报表时才会用到,安装matplotlib你的系统有可能需要安装libpng和freetype库。</li>
</ul>
</div>
<div class="section" id="id2">
<h2>2. 使用方法</h2>
<ul class="simple">
<li>创建项目 …</li></ul></div><p>对Web服务做Performance & Load测试,最常见的工具有<a class="reference external" href="http://httpd.apache.org/docs/2.2/programs/ab.html">Apache
Benchmark</a>俗称ab和商用工具LoadRunner。ab简单直接,功能也相对较弱,但我们经常看到的对一些Web
server或者Framework的性能测试用的ab做的,而LoadRunner功能也确实很强大,各种大型软件公司、软件外包企业几乎是必备了,用起来很High,当然其价格也确实很High
:)</p>
<p>这里要介绍的<a class="reference external" href="https://github.com/cgoldberg/multi-mechanize">multi-mechanize(</a>这名忒难记)是一款用Python开发的Performance
&
Load测试工具,是由<a class="reference external" href="http://pylot.org/">Pylot</a>的作者新近开发的,算是升级换代的产品。用multi-mechanize可以通过编写Python脚本来实现较复杂的测试逻辑,其并发测试是通过multiprocessing(多进程)和多线程机制来实现的。</p>
<div class="section" id="id1">
<h2><strong>1. 安装</strong></h2>
</div>
<div class="section" id="pip-easy-install">
<h2>万能的pip&easy_install</h2>
</div>
<div class="section" id="pip-install-multi-mechanize-mechanize-numpy-matplotlib">
<h2>pip install multi-mechanize mechanize numpy matplotlib</h2>
<ul class="simple">
<li>mechanize是一个模拟browser行为的一个库,当然你也可以用其它的如urllib2、request、tornado.httpclient等等库,不是必须。</li>
<li>后面两个numpy和matplotlib也是可选的,当你需要它自动生成图形化报表时才会用到,安装matplotlib你的系统有可能需要安装libpng和freetype库。</li>
</ul>
</div>
<div class="section" id="id2">
<h2>2. 使用方法</h2>
<ul class="simple">
<li>创建项目</li>
</ul>
<pre class="literal-block">
multimech-newproject my_project
</pre>
<p>自动创建一个my_project目录,子目录test_scripts用来放测试脚本,config.cfg是测试配置,主要要配的是测试时间、测试脚本和并发threads量。</p>
<ul class="simple">
<li>脚本编写,借用官方的一个简单例子:</li>
</ul>
<div class="highlight"><pre><span></span><span class="c1">#</span>
<span class="c1"># Copyright (c) 2010 Corey Goldberg (corey@goldb.org)</span>
<span class="c1"># License: GNU LGPLv3</span>
<span class="c1">#</span>
<span class="c1"># This file is part of Multi-Mechanize</span>
<span class="c1">#</span>
<span class="kn">import</span> <span class="nn">mechanize</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="k">class</span> <span class="nc">Transaction</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">custom_timers</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">br</span> <span class="o">=</span> <span class="n">mechanize</span><span class="o">.</span><span class="n">Browser</span><span class="p">()</span>
<span class="n">br</span><span class="o">.</span><span class="n">set_handle_robots</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="n">start_timer</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
<span class="n">resp</span> <span class="o">=</span> <span class="n">br</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">'http://www.example.com/'</span><span class="p">)</span>
<span class="n">resp</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">latency</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start_timer</span>
<span class="bp">self</span><span class="o">.</span><span class="n">custom_timers</span><span class="p">[</span><span class="s1">'Example_Homepage'</span><span class="p">]</span> <span class="o">=</span> <span class="n">latency</span>
<span class="k">assert</span> <span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">),</span> <span class="s1">'Bad HTTP Response'</span>
<span class="k">assert</span> <span class="p">(</span><span class="s1">'Example Web Page'</span> <span class="ow">in</span> <span class="n">resp</span><span class="o">.</span><span class="n">get_data</span><span class="p">()),</span> <span class="s1">'Failed Content Verification'</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">trans</span> <span class="o">=</span> <span class="n">Transaction</span><span class="p">()</span>
<span class="n">trans</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="k">print</span> <span class="n">trans</span><span class="o">.</span><span class="n">custom_timers</span>
</pre></div>
<p>注意:按multi-mechanize的默认规则,每个脚本必须有一个Transaction的类,类要有一个run方法,在run里面写测试业务逻辑。这个例子是打开http://www.example.com,记录访问所耗时长,非常简单明了,而实际的场景你可能需要有用户登录、然后测试某个或多个页面(API),只是测试业务复杂一些,写法是类似的。一个脚本文件只能有一个Transaction的类、类也只能有一个run方法,写起case来是不是觉得非常不方便?不用急,针对这点,后面的小技巧部分会另辟蹊径给你指条明路。</p>
<ul class="simple">
<li>运行项目的测试脚本</li>
</ul>
<pre class="literal-block">
multimech-run my_project
</pre>
<p>测试结果报表和原始数据将放到results目录下按测试时间生成的子目录中,生产的html版本的结果统计如下图所示:</p>
<p><a class="reference external" href="/static/2013/02/multi-mechanize-report.jpg"><img alt="image0" src="/static/2013/02/multi-mechanize-report.jpg" style="width: 881px; height: 942px;" /></a></p>
</div>
<div class="section" id="id3">
<h2>3. 使用小技巧</h2>
<ul class="simple">
<li>Cookie:</li>
</ul>
<p>如果使用的是mechanize,可以通过下面的方式,从上面的browser对象br里获取到cookie信息。</p>
<p>br._ua_handlers["_cookies"].cookieja</p>
<ul class="simple">
<li>单个脚本多个测试用例的支持:这个思路来源于testsuite的概念,同一个testsuite里的case作为一组相关的case可以共享一些代码逻辑和资源(如browser对象),而multi-mechanize默认的方式是不支持的,要实现这一点,只需要一点小小的技巧即可,上代码:</li>
<li>真实的并发量计算:multi-mechanize使用了multiprocessing库,会同时起多个进程,且每个进程按config里的配置起多个线程来实现并发测试,但真正的单位时间内的并发量并不是config里设置threads=10这样的表示每秒10个并发,真实的并发量需要根据最终完成的transaction数和这些transaction里面包含多少次http请求和总的完成时间来计算得知,这点不是很直观。</li>
<li>自定义统计数据:你可以往self.custom_timers这个内建的字典里塞任意的自定义统计数据,他们在报表中都能够得到体现。</li>
</ul>
<p>更多的文档和一手资料请参考文档<a class="reference external" href="http://testutils.org/multi-mechanize/">http://testutils.org/multi-mechanize/</a>和git代码库<a class="reference external" href="https://github.com/cgoldberg/multi-mechanize%20">https://github.com/cgoldberg/multi-mechanize</a>。最后multi-mechanize还不是很好用,一是使用过程中发现有一些情况会抛异常,导致不能正确生成报表,另一个别扭的是case的编写不是unittest那一套,是作者自创Transaction流:)</p>
</div>
用Tornado开发RESTful API运用2012-10-22T11:56:00+08:002012-10-22T11:56:00+08:00飞龙tag:feilong.me,2012-10-22:/2012/10/developing-restful-api-with-tornado.html<p>《用Tornado开发RESTful API应用》,这是我在PyconCN
2012上做的演讲主题,我原计划对此大概讲个30分钟,不过现场主持好像把我的这个主题归类到快速演讲里,或者是我之前没搞清楚吧,所以现场我对演讲的内容做了一些压缩,节奏也比较快,一些内容没有时间来做展开,对实现细节有兴趣的朋友可以去看我的演讲Slides和开源出来的d3status这个demo的源代码,源代码放在 <a class="reference external" href="https://github.com/felinx/d3status">https://github.com/felinx/d3status</a>,演讲Slides的下载链接见 <a class="reference external" href="/static/2012/10/用Tornado开发RESTful-API运用.pdf">用Tornado开发RESTful
API运用</a>,你也可以通过下面内嵌的Slides直接查看,不过因为Slides放在slideshare上,需要翻墙。</p>
<p><a class="reference external" href="http://www.slideshare.net/FelinxLee/tornadorestful-api">用Tornado开发RESTful
API运用</a>
from <a class="reference external" href="http://www.slideshare.net/FelinxLee">Felinx Lee</a></p>
<p>特别说明:</p>
<div class="line-block">
<div class="line">1.
本次PyconCN事后有不少人吐槽广告比较多而干货少,我这个不算干货也不算广告,硬要说是广告的话,那就是我免费给Tornado打了个广告:)</div>
<div class="line">2.
有朋友在github上提出对d3status的ios客户端感兴趣,问能不能开源?答:因为iPhone
APP的ObjC代码是朋友写的,这个暂时不考虑开源。</div>
<div class="line">3.
d3status这个demo虽然很小,但五脏俱全,且d3status的骨架抽取自我们线上运行了有近一年的app的源代码,有一定的参考和学习价值。</div>
</div>
<p>《用Tornado开发RESTful API应用》,这是我在PyconCN
2012上做的演讲主题,我原计划对此大概讲个30分钟,不过现场主持好像把我的这个主题归类到快速演讲里,或者是我之前没搞清楚吧,所以现场我对演讲的内容做了一些压缩,节奏也比较快,一些内容没有时间来做展开,对实现细节有兴趣的朋友可以去看我的演讲Slides和开源出来的d3status这个demo的源代码,源代码放在 <a class="reference external" href="https://github.com/felinx/d3status">https://github.com/felinx/d3status</a>,演讲Slides的下载链接见 <a class="reference external" href="/static/2012/10/用Tornado开发RESTful-API运用.pdf">用Tornado开发RESTful
API运用</a>,你也可以通过下面内嵌的Slides直接查看,不过因为Slides放在slideshare上,需要翻墙。</p>
<p><a class="reference external" href="http://www.slideshare.net/FelinxLee/tornadorestful-api">用Tornado开发RESTful
API运用</a>
from <a class="reference external" href="http://www.slideshare.net/FelinxLee">Felinx Lee</a></p>
<p>特别说明:</p>
<div class="line-block">
<div class="line">1.
本次PyconCN事后有不少人吐槽广告比较多而干货少,我这个不算干货也不算广告,硬要说是广告的话,那就是我免费给Tornado打了个广告:)</div>
<div class="line">2.
有朋友在github上提出对d3status的ios客户端感兴趣,问能不能开源?答:因为iPhone
APP的ObjC代码是朋友写的,这个暂时不考虑开源。</div>
<div class="line">3.
d3status这个demo虽然很小,但五脏俱全,且d3status的骨架抽取自我们线上运行了有近一年的app的源代码,有一定的参考和学习价值。</div>
</div>
Tornado对子域名和泛域名的支持2012-08-20T12:42:00+08:002012-08-20T12:42:00+08:00飞龙tag:feilong.me,2012-08-20:/2012/08/wildcard-subdomain-support-in-tornado.html<p>其实Tornado对子域名和泛域名(除了特别说明外,以下子域名和泛域名均简称为泛域名)的支持并不是什么新鲜事,两年多前我用Tornado写的开源网站
<a class="reference external" href="http://poweredsites.org">http://poweredsites.org</a>
就有了对泛域名的支持,但是Tornado的官方文档里并没有明确对此功能进行说明,虽然源代码里是有注释的,终是有点隐晦,这不,近日mywaiting同学就遇到了这个问题,我应邀特撰此博文,分享下我对此的一点点经验。</p>
<p>通常,用Tornado添加url映射路由表是直接传handlers给Application这种方式的,比如官方的chatdemo:</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Application</span><span class="p">(</span><span class="n">tornado</span><span class="o">.</span><span class="n">web</span><span class="o">.</span><span class="n">Application</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">handlers</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">MainHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/auth/login"</span><span class="p">,</span> <span class="n">AuthLoginHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/auth/logout"</span><span class="p">,</span> <span class="n">AuthLogoutHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/a/message/new"</span><span class="p">,</span> <span class="n">MessageNewHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/a/message/updates"</span><span class="p">,</span> <span class="n">MessageUpdatesHandler</span><span class="p">),</span>
<span class="p">]</span>
<span class="n">settings</span> <span class="o">=</span> <span class="nb">dict …</span></pre></div><p>其实Tornado对子域名和泛域名(除了特别说明外,以下子域名和泛域名均简称为泛域名)的支持并不是什么新鲜事,两年多前我用Tornado写的开源网站
<a class="reference external" href="http://poweredsites.org">http://poweredsites.org</a>
就有了对泛域名的支持,但是Tornado的官方文档里并没有明确对此功能进行说明,虽然源代码里是有注释的,终是有点隐晦,这不,近日mywaiting同学就遇到了这个问题,我应邀特撰此博文,分享下我对此的一点点经验。</p>
<p>通常,用Tornado添加url映射路由表是直接传handlers给Application这种方式的,比如官方的chatdemo:</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Application</span><span class="p">(</span><span class="n">tornado</span><span class="o">.</span><span class="n">web</span><span class="o">.</span><span class="n">Application</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">handlers</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">MainHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/auth/login"</span><span class="p">,</span> <span class="n">AuthLoginHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/auth/logout"</span><span class="p">,</span> <span class="n">AuthLogoutHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/a/message/new"</span><span class="p">,</span> <span class="n">MessageNewHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/a/message/updates"</span><span class="p">,</span> <span class="n">MessageUpdatesHandler</span><span class="p">),</span>
<span class="p">]</span>
<span class="n">settings</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
<span class="n">cookie_secret</span><span class="o">=</span><span class="s2">"43oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo="</span><span class="p">,</span>
<span class="n">login_url</span><span class="o">=</span><span class="s2">"/auth/login"</span><span class="p">,</span>
<span class="n">template_path</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s2">"templates"</span><span class="p">),</span>
<span class="n">static_path</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s2">"static"</span><span class="p">),</span>
<span class="n">xsrf_cookies</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
<span class="n">autoescape</span><span class="o">=</span><span class="s2">"xhtml_escape"</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">tornado</span><span class="o">.</span><span class="n">web</span><span class="o">.</span><span class="n">Application</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handlers</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">)</span>
</pre></div>
<p>这种方式其实添加的是一个域名通配的url映射表,即域名&子域名不限,只要访问能够解析到这个chatdemo上,“/auth/login”
“/auth/login”这些url就都能够正常运行。假设www.feilong.me、abc.feilong.me、feilong2.me这个三个(子)域名均配置为可由这个chatdemo程序来host,那么访问这三个(子)域名均可以正常使用这个chatdemo,总之域名是无关的。</p>
<p>实际上,这种方式它的内部是通过Application里的这个add_handlers来实现的(原码注释如下):</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">add_handlers</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host_pattern</span><span class="p">,</span> <span class="n">host_handlers</span><span class="p">):</span>
<span class="sd">"""Appends the given handlers to our handler list.</span>
<span class="sd"> Note that host patterns are processed sequentially in the</span>
<span class="sd"> order they were added, and only the first matching pattern is</span>
<span class="sd"> used. This means that all handlers for a given host must be</span>
<span class="sd"> added in a single add_handlers call.</span>
<span class="sd"> """</span>
</pre></div>
<p>只不过它是隐式的调用这个add_handlers而已,其关键点就在于第一个参数host_pattern(匹配域名的)上,上面那种方式,默认添加的host_pattern是".*$",即域名通配,若要支持泛域名,只需要显式的调用add_handlers来添加相应的host_pattern和handlers即可。</p>
<p>接下来就以<a class="reference external" href="https://bitbucket.org/felinx/poweredsites">poweredsites的源码</a>来介绍Tornado对泛域名的支持,app.py里的Application里面有这么几句:</p>
<div class="highlight"><pre><span></span><span class="nb">super</span><span class="p">(</span><span class="n">Application</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">handlers</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">)</span>
<span class="c1"># add handlers for sub domains</span>
<span class="k">for</span> <span class="n">sub_handler</span> <span class="ow">in</span> <span class="n">sub_handlers</span><span class="p">:</span>
<span class="c1"># host pattern and handlers</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_handlers</span><span class="p">(</span><span class="n">sub_handler</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">sub_handler</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
<p>常见的方式super(Application, self).__init__(handlers,
**settings)添加的是根域名poweredsites的handlers,接着用for循环显式添加的是子域名和泛域名的handlers。这里的sub_handlers依次放有各子域名的handlers,其最后一个是泛域名的handlers:</p>
<div class="highlight"><pre><span></span><span class="n">sub_handlers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">sub_handlers</span><span class="p">)</span>
<span class="n">sub_handlers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">blog</span><span class="o">.</span><span class="n">sub_handlers</span><span class="p">)</span>
<span class="n">sub_handlers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">sub_handlers</span><span class="p">)</span>
<span class="c1"># wildcard subdomain handler for project should be the last one.</span>
<span class="n">sub_handlers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">project</span><span class="o">.</span><span class="n">sub_handlers</span><span class="p">)</span>
</pre></div>
<p>指定的子域名的sub_handlers(site.sub_handlers)是这个样子的,这里的第一个元素就是host_pattern:</p>
<div class="highlight"><pre><span></span><span class="n">sub_handlers</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"^sites.poweredsites.org$"</span><span class="p">,</span>
<span class="p">[</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">_WebsiteIndexHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/feeds"</span><span class="p">,</span> <span class="n">_WebsitesFeedsHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/([a-z0-9]{32})"</span><span class="p">,</span> <span class="n">_WebsiteHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/([^/]+)"</span><span class="p">,</span> <span class="n">WebsiteHandler</span><span class="p">),</span>
<span class="p">]</span>
<span class="p">]</span>
</pre></div>
<p>泛域名(project.sub_handlers)的区别也就在于这第一个元素,即用来做host_pattern的是通配一些子域名的:</p>
<div class="highlight"><pre><span></span><span class="n">sub_handlers</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"^[a-zA-Z_\-0-9]*\.poweredsites.org$"</span><span class="p">,</span>
<span class="p">[(</span><span class="sa">r</span><span class="s2">"/"</span><span class="p">,</span> <span class="n">ProjectIndexHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/top"</span><span class="p">,</span> <span class="n">ProjectTopHandler</span><span class="p">),</span>
<span class="p">(</span><span class="sa">r</span><span class="s2">"/opensource"</span><span class="p">,</span> <span class="n">ProjectOpensourceHandler</span><span class="p">),</span>
<span class="p">]</span>
<span class="p">]</span>
</pre></div>
<p>在用到了泛域名的ProjectIndexHandler里,运行时具体的子域名就可以通过下面这样的方式获得:</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">ProjectIndexHandler</span><span class="p">(</span><span class="n">ProjectBaseHandler</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">subdomain</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">host</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</pre></div>
<p>需要说明的是,Tornado里面的url映射表和Django一样是有顺序的,即url依次序由上到下匹配,只要匹配到就立即结束,不再往下匹配,而带子域名和泛域名的url路由其匹配优先级是要高于通配域名".*$"的(这个不用你操心,add_handlers会自动为你做到这一点)。同样的,对于泛域名,因为其子域名是通配的,因此指定子域名的handlers需要放到泛域名前添加,如admin、blog这类子域名的handlers要放在泛域名之前,这就是poweredsites里sub_handlers.append(project.sub_handlers)放到最后一条的原因,project这条是对应泛域名的,<a class="reference external" href="http://tornado.poweredsites.org">http://tornado.poweredsites.org</a>
就是靠这一条来实现的。</p>
<p>备注:需要支持泛域名,首先要你的域名解析支持泛域名。</p>
有趣的Python闭包(Closures)2012-06-03T13:23:00+08:002012-06-03T13:23:00+08:00飞龙tag:feilong.me,2012-06-03:/2012/06/interesting-python-closures.html<p>写下这篇博客,起源于Tornado邮件群组的这个问题 <a class="reference external" href="http://groups.google.com/group/python-tornado/browse_thread/thread/d10165015eb293c1">how to use outer variable
in inner
method</a>,这里面老外的回答很有参考价值,关键点基本都说到了。我在这里用一些有趣的例子来做些解析,简要的阐述下Python的闭包规则,首先看一个经典的例子:</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">bar</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span>
<span class="c1"># print a + 1</span>
<span class="c1"># b = a + 1</span>
<span class="c1"># a = 1</span>
<span class="k">print</span> <span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">bar</span><span class="p">()</span>
<span class="k">print</span> <span class="n">a</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
</pre></div>
<p>在Python2.x上运行这个函数会报UnboundLocalError: local variable 'a' referenced before assignment即本地变量在引用前未定义,如何来理解这个错误呢?PEP …</p><p>写下这篇博客,起源于Tornado邮件群组的这个问题 <a class="reference external" href="http://groups.google.com/group/python-tornado/browse_thread/thread/d10165015eb293c1">how to use outer variable
in inner
method</a>,这里面老外的回答很有参考价值,关键点基本都说到了。我在这里用一些有趣的例子来做些解析,简要的阐述下Python的闭包规则,首先看一个经典的例子:</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">bar</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span>
<span class="c1"># print a + 1</span>
<span class="c1"># b = a + 1</span>
<span class="c1"># a = 1</span>
<span class="k">print</span> <span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">bar</span><span class="p">()</span>
<span class="k">print</span> <span class="n">a</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
</pre></div>
<p>在Python2.x上运行这个函数会报UnboundLocalError: local variable 'a' referenced before assignment即本地变量在引用前未定义,如何来理解这个错误呢?PEP
227里面介绍到,Python解析器在搜索一个变量的定义时是根据如下三级规则来查找的:</p>
<blockquote>
The Python 2.0 definition specifies exactly three namespaces to
check for each name -- the local namespace, the global namespace,
and the builtin namespace.</blockquote>
<p>这里的local实际上可能还有多级,上面的代码就是一个例子,下面通过对代码做些简单的修改来一步步理解这里面的规律:</p>
<ul class="simple">
<li>如果将a = a + 1这句换成print a + 1或者b = a +
1,是不会有问题的,即在内部函数bar内,外部函数foo里的a实际是可见的,可以引用。</li>
<li>将a = a + 1换成 a =
1也是没有问题的,但是如果你将两处出现的a的id打印出来你会发现,其实这两个a不是一回事,在内部函数bar里面,本地的a
=
1定义了在bar函数范围内的新的一个局部变量,因为名字和外部函数foo里面的变量a名字相同,导致外部函数foo里的a在内部函数bar里实际已不可见。</li>
<li>再来说a = a + 1出错是怎么回事,首先a =
xxx这种形式,Python解析器认为要在内部函数bar内创建一个新的局部变量a,同时外部函数foo里的a在bar里已不可见,而解析器对接下来对右边的a
+
1的解析就是用本地的变量a加1,而这时左边的a即本地的变量a还没有创建(等右边赋值呢),因此就这就产生了一个是鸡生蛋还是蛋生鸡的问题,导致了上面说的UnboundLocalError的错误。</li>
</ul>
<p>要解决这个问题,在Python2.x里主要有两个方案:</p>
<ol class="arabic">
<li><p class="first">用别名替代比如b = a + 1,内部函数bar内只引用外部函数foo里的a。</p>
</li>
<li><p class="first">将foo里的a设成一个容器,如list</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="p">]</span>
<span class="k">def</span> <span class="nf">bar</span><span class="p">():</span>
<span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">bar</span><span class="p">()</span>
<span class="k">print</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</pre></div>
</li>
</ol>
<p>当然这有些时候还是很不方便,因此在Python3.x中引入了一个nonloacal的关键字来解决这个问题,只要在a
= a + 1前加一句nonloacal
a即可,即显式的指定a不是内部函数bar内的本地变量,这样就可以在bar内正常的使用和再赋值外部函数foo内的变量a了。</p>
<p>在搜索Python闭包相关的材料中,我在StackOverflow上发现一个有趣的有关Python闭包的问题,有兴趣的可以思考思考做做看,结果应该是什么?你预期的结果是什么,若不一致,如果要得到你预期的结果应该怎么改?</p>
<div class="highlight"><pre><span></span><span class="n">flist</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">i</span>
<span class="n">flist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">flist</span><span class="p">:</span>
<span class="k">print</span> <span class="n">f</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
<p>扩展阅读:</p>
<ol class="arabic simple">
<li><a class="reference external" href="http://www.python.org/dev/peps/pep-0227/">PEP 227 -- Statically Nested
Scopes</a></li>
<li><a class="reference external" href="http://www.python.org/dev/peps/pep-3104/">PEP 3104 -- Access to Names in Outer
Scopes</a></li>
<li><a class="reference external" href="http://stackoverflow.com/questions/233673/lexical-closures-in-python">Lexical closures in
Python</a></li>
</ol>
那些年我们一起被偷的东西2012-06-03T10:18:00+08:002012-06-03T10:18:00+08:00飞龙tag:feilong.me,2012-06-03:/2012/06/things-have-been-stolen-in-those-years.html<p>2012年5月30日,我用了仅3个月的白色iPhone
4S在世纪大道地铁站上电梯时被偷,再一次被偷不禁让我想起那些年我们一起被偷的东西。</p>
<p>遥想一下小时候在农村(80年代),家家门不闭户,道不拾遗,几乎没有被偷的事情发生;当我读高中的时候(90年代初)偶尔听说村里有人偷鸡摸狗;到了读大学的时候(90年代末),自行车和寝室被偷这类事情时有耳闻,听的比较多的案例是晚上小偷从窗子那把衣服裤子勾走,当然他们主要看中的是里面的钱包,不过我好像没有这样被偷过。时间一旦迈入了21世纪,一连串杯具就开始了:</p>
<ol class="arabic simple">
<li>2000年,我大学要好的同学买了辆新自行车,我也经常蹭他这辆车,这自行车有个小毛病就是座椅比较松老是歪歪扭扭的,骑坐时很不舒服,有一天我们两人实在忍受不了这座椅,找来扳手和老虎钳子费了九牛二虎之力终于把座椅修好,第二天这自行车就不翼而飞了。我说小偷,座椅坏的那么长时间,你咋就看不上它呢?刚弄好你就盯上了,你眼睛还真毒啊!此次被偷虽然偷的不是我的东西,但跟我也有比较大的关系,所以这里也记录一笔。</li>
<li>2001年,当时我刚认识现在我的老婆红太龙,那正是咱俩甜蜜缠绵心无旁骛的时候:)。有一次在武汉大学校门口的录像厅一起看录像,下半夜,就放我们身边的包包被人翻了个底朝天,红太龙的钱包被人摸走了,那钱包可是我送给红太龙的第一个礼物啊,红太龙喜欢的不得了,小偷你也忍心偷啊......</li>
<li>2005年,重灾年。我那时租住在武大旁边的东湖新村,有大量的学生在此租房 …</li></ol><p>2012年5月30日,我用了仅3个月的白色iPhone
4S在世纪大道地铁站上电梯时被偷,再一次被偷不禁让我想起那些年我们一起被偷的东西。</p>
<p>遥想一下小时候在农村(80年代),家家门不闭户,道不拾遗,几乎没有被偷的事情发生;当我读高中的时候(90年代初)偶尔听说村里有人偷鸡摸狗;到了读大学的时候(90年代末),自行车和寝室被偷这类事情时有耳闻,听的比较多的案例是晚上小偷从窗子那把衣服裤子勾走,当然他们主要看中的是里面的钱包,不过我好像没有这样被偷过。时间一旦迈入了21世纪,一连串杯具就开始了:</p>
<ol class="arabic simple">
<li>2000年,我大学要好的同学买了辆新自行车,我也经常蹭他这辆车,这自行车有个小毛病就是座椅比较松老是歪歪扭扭的,骑坐时很不舒服,有一天我们两人实在忍受不了这座椅,找来扳手和老虎钳子费了九牛二虎之力终于把座椅修好,第二天这自行车就不翼而飞了。我说小偷,座椅坏的那么长时间,你咋就看不上它呢?刚弄好你就盯上了,你眼睛还真毒啊!此次被偷虽然偷的不是我的东西,但跟我也有比较大的关系,所以这里也记录一笔。</li>
<li>2001年,当时我刚认识现在我的老婆红太龙,那正是咱俩甜蜜缠绵心无旁骛的时候:)。有一次在武汉大学校门口的录像厅一起看录像,下半夜,就放我们身边的包包被人翻了个底朝天,红太龙的钱包被人摸走了,那钱包可是我送给红太龙的第一个礼物啊,红太龙喜欢的不得了,小偷你也忍心偷啊......</li>
<li>2005年,重灾年。我那时租住在武大旁边的东湖新村,有大量的学生在此租房,道理你懂的,相对的管理和治安也比较混乱。我的第一部手机Nokia
8250不幸在这里遇难,我住的是二楼,床位靠窗,一天晚上睡觉前我把手机放枕边,第二天早上醒来发现手机不见了,房门没有任何被动过的痕迹,也就是说小偷是爬上二楼外墙,从窗子那正对着我的脸偷走我手机的,想想我就有点渗的慌。手机被偷后,灾难还没有结束,几天后的大白天,乘我去买火车票短期不在家的当口,小偷大白天破门而入(没错是破门而入),把我当时的那台电脑主机偷走了(里面珍藏有我自己多年的星际录像和博德之门系列存档),家里被翻的乱七八糟,小偷忙里偷闲顺手牵羊还偷走了我老婆送来的一盒月饼(不知道是不是还忙里偷闲咬着月饼行窃的),月饼盒子他倒是没有拿走,卡和证件啥的也给我留了,良心大大的好,我还得赞他一下。</li>
<li>2006年,05年底我来到了上海,在华为上海研究所上班,华为当时对手机的使用有规定,不解释,反正只能用很挫的手机,我买了一部500块左右的索爱手机,还带100块花费的,具体型号不记得了,因为很快就被偷走了,事发在06年年初,被偷的过程也很简单,早上挤出了名的挤的970路公交车的时候被偷,我纳闷的是这么搓的手机小偷也不放过,这小偷也挺可怜的。</li>
<li>2009年,这一年我买的第一步智能机索爱P1义无反顾的去见小偷了。P1买的时候花了我3000块大洋,也是一笔血汗钱啊,后来被红太龙借用就不还了:(。一次红太龙和我妈妈带着我女儿逛家乐福,在一次接完电话后红太龙随手把手机放到了购物车上自带的包包里,结果被小偷盯上了。放的时候老妈当时还说了句“放这里不安全吧”,红太龙没有引起足够的重视,天真的认为家乐福这么大的超市不至于此。被偷后报案,家乐福工作人员表示,手机被偷的事常有,我们在购物推车上也有提示,不要将贵重物品放里面。后来也调看了监控录像,说人多比较模糊,无果!</li>
<li>2012年5月30日,我用了仅3个月的白色iPhone
4S在世纪大道地铁站上电梯时被偷,本出于安全考虑我准备把背在后背的双肩包换到胸前,这时我错误的临时把手机放到了相对宽松的上衣口袋中(用这部手机以来这还是头一次放上衣口袋),等我把包背好再来掏手机的时候手机就被偷了,这个过程前后差不多也就一秒钟,但当时人太多分且事发恰好在上电梯口那里,我分不清是电梯上还是电梯下的人所为,身上多处搜查后确认手机被偷,我马上用我另一手机拨打了我的4S,手机已经被关机了,这时离事发不满一分钟,很遗憾最终我没能找到小偷。后来我报了案,来了好几个民警调查了下现场,民警让他们的上级调看了事发时的监控录像,给我的回答也是当时人比较多看不清楚,无果!民警例行的按模版记录此次被偷事件,前后搞了差不多一个小时,最后打印盖章了一张报案回单给我让我回去等最新消息,无果!我上班地铁上的时间比较长且揣的电子设备比较多,鉴于此前的被偷经历我平时已是非常的小心警觉,但这次比较意外的一次疏忽就被小偷逮了个正着,真是千提防万提防小偷防不甚防。昨日我去联通营业厅咨询手机补卡的时候,营业员跟我讲iPhone被偷是家常便饭,iPhone被偷的远不止我一个。</li>
</ol>
<p>纵观我自己亲身经历的这些被偷事件:</p>
<ol class="arabic simple">
<li>地铁、公交、超市、学校等人多聚集的地方是重灾区。</li>
<li>手机特别是iPhone系列是小偷重点照顾对象。</li>
<li>不贴身的位置千万不能放贵重物品,比如购物推车、上衣靠边的口袋。</li>
<li>监控录像只是用来方便做假证的,关键时刻都是模糊的。</li>
<li>盗人之心不可有,防盗之心不可无。小偷太猖獗,他们日夜忙碌只为一招得手,防不胜防,你我不能有片刻的马虎。</li>
<li>无一技之长讨生活选择习偷窃技能的人是越来越多,和谐社会天下无贼那是痴人说梦。</li>
</ol>
<p><img alt="image0" class="size-full wp-image-720 aligncenter" src="/static/2012/06/without-thief.jpg" style="width: 361px; height: 337px;" /></p>
<p>现在我坐地铁见到稍微长得猥琐点的人,就会带有色眼睛怀疑下这人会不会是小偷,已经到了神经质的地步,然而6月1日我在拥挤的地铁上无意间碰到一位MM的包包,MM当时瞟了我一眼后,马上就把包包换到胸前去了,难道我很猥琐很像小偷?看来被害得神经质的人远不止我一个,这事耐人寻味啊....</p>
<p><strong>坐下来记这笔流水账,只为悼念下那些年我们一起被偷的东西。</strong></p>
用Tornado实现简单的在线代理2011-09-10T23:13:00+08:002011-09-10T23:13:00+08:00飞龙tag:feilong.me,2011-09-10:/2011/09/tornado-as-a-proxy.html<p>实现代理的方式很多种,流行的web服务器也大都有代理的功能,比如<a class="reference external" href="http://www.tornadoweb.cn">http://www.tornadoweb.cn</a>用的就是nginx的代理功能做的tornadoweb官网的镜像。</p>
<p>最近,我在开发一个移动运用(以下简称APP)的后台程序(Server),该运用需要调用到另一平台产品(Platform)的API。对于这个系统来说,可选的一种实现方式方式是APP同时跟Server&Platform两者交互;另一种则在Server端封装掉Platform的API,APP只和Server交互。显然后一种方式的系统架构会清晰些,APP编程时也就相对简单。那么如何在Server端封装Platform的API呢,我首先考虑到的就是用代理的方式来实现。碰巧最近Tornado邮件群组里有人在讨论<a class="reference external" href="http://groups.google.com/group/python-tornado/browse_thread/thread/4c1ffaa0a0667650?pli=1">using
Tornado as a
proxy</a>,贴主提到的运用场景跟我这碰到的场景非常的相似,我把原帖的代码做了些整理和简化,源代码如下:</p>
<pre class="literal-block">
# -*- coding: utf-8 -*-
#
# Copyright(c) 2011 Felinx Lee & http://feilong.me/
#
# Licensed under the Apache License, Version …</pre><p>实现代理的方式很多种,流行的web服务器也大都有代理的功能,比如<a class="reference external" href="http://www.tornadoweb.cn">http://www.tornadoweb.cn</a>用的就是nginx的代理功能做的tornadoweb官网的镜像。</p>
<p>最近,我在开发一个移动运用(以下简称APP)的后台程序(Server),该运用需要调用到另一平台产品(Platform)的API。对于这个系统来说,可选的一种实现方式方式是APP同时跟Server&Platform两者交互;另一种则在Server端封装掉Platform的API,APP只和Server交互。显然后一种方式的系统架构会清晰些,APP编程时也就相对简单。那么如何在Server端封装Platform的API呢,我首先考虑到的就是用代理的方式来实现。碰巧最近Tornado邮件群组里有人在讨论<a class="reference external" href="http://groups.google.com/group/python-tornado/browse_thread/thread/4c1ffaa0a0667650?pli=1">using
Tornado as a
proxy</a>,贴主提到的运用场景跟我这碰到的场景非常的相似,我把原帖的代码做了些整理和简化,源代码如下:</p>
<pre class="literal-block">
# -*- coding: utf-8 -*-
#
# Copyright(c) 2011 Felinx Lee & http://feilong.me/
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
from tornado.web import HTTPError, asynchronous
from tornado.httpclient import HTTPRequest
from tornado.options import define, options
try:
from tornado.curl_httpclient import CurlAsyncHTTPClient as AsyncHTTPClient
except ImportError:
from tornado.simple_httpclient import SimpleAsyncHTTPClient as AsyncHTTPClient
define("port", default=8888, help="run on the given port", type=int)
define("api_protocol", default="http")
define("api_host", default="feilong.me")
define("api_port", default="80")
define("debug", default=True, type=bool)
class ProxyHandler(tornado.web.RequestHandler):
@asynchronous
def get(self):
# enable API GET request when debugging
if options.debug:
return self.post()
else:
raise HTTPError(405)
@asynchronous
def post(self):
protocol = options.api_protocol
host = options.api_host
port = options.api_port
# port suffix
port = "" if port == "80" else ":%s" % port
uri = self.request.uri
url = "%s://%s%s%s" % (protocol, host, port, uri)
# update host to destination host
headers = dict(self.request.headers)
headers["Host"] = host
try:
AsyncHTTPClient().fetch(
HTTPRequest(url=url,
method="POST",
body=self.request.body,
headers=headers,
follow_redirects=False),
self._on_proxy)
except tornado.httpclient.HTTPError, x:
if hasattr(x, "response") and x.response:
self._on_proxy(x.response)
else:
logging.error("Tornado signalled HTTPError %s", x)
def _on_proxy(self, response):
if response.error and not isinstance(response.error,
tornado.httpclient.HTTPError):
raise HTTPError(500)
else:
self.set_status(response.code)
for header in ("Date", "Cache-Control", "Server", "Content-Type", "Location"):
v = response.headers.get(header)
if v:
self.set_header(header, v)
if response.body:
self.write(response.body)
self.finish()
def main():
tornado.options.parse_command_line()
application = tornado.web.Application([
(r"/.*", ProxyHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
</pre>
<p>运行上面的代码后,访问 <a class="reference external" href="http://localhost:8888/">http://localhost:8888/</a>
将会完整显示飞龙博客的首页,即代理访问了http://feilong.me/的内容。</p>
<p>我考虑用程序的方式来做代理而不是直接用Nginx来做代理,其中一点是考虑到用程序可以很容易的控制Platform的哪些API是需要代理的,而哪些是要屏蔽掉的,还有哪些可能是要重写的(比如Server的login可能不能直接代理Platform的login,但却要调用到Platform的login
API)。</p>
<p>以上这段代码只是做了简单的页面内容代理,并没有对页面进行进一步的解析处理,比如链接替换等,这些就交个有兴趣的朋友去开发了。基于以上这段代码,将其扩展一下,是完全可以实现一个完整的在线代理程序的。</p>
<p>这段代码我已放到了我的实验项目里,见<a class="reference external" href="https://bitbucket.org/felinx/labs">https://bitbucket.org/felinx/labs</a>,我将会放更多类似于这样的实验性质的小项目到这个repository里来,有兴趣的朋友可以关注一下。</p>
9月1日入职盛大创新院2011-09-01T07:34:00+08:002011-09-01T07:34:00+08:00飞龙tag:feilong.me,2011-09-01:/2011/09/join-shanda-innovations.html<p>9月1日是传统的入学的日子,宝宝今日入学幼儿园中班,爷爷奶奶一起送她去上学,老婆(老师)今天正式开学,而我则挑了这么个特殊的日子,在昨天匆匆忙忙告别Autodesk之后今日入职盛大创新院。今天全家出动,对我们可谓一个新的开始。</p>
<p>去年CSDN
SD大会碰巧坐<a class="reference external" href="http://weibo.com/n/%E4%BD%99%E5%B0%8F%E6%B3%A2">@余小波</a>旁,休息期间跟着余一起碰到了<a class="reference external" href="http://weibo.com/n/dreamsoft">@dreamsoft</a>
(人称老郭的创新院郭院长),当时我就震惊了,这居然是一院之长,太低调太Geek了吧,我毫无免疫力的瞬间成为老郭粉丝。</p>
<p>话说回来当时能去参加SD大会,完全是因为从<a class="reference external" href="http://weibo.com/n/pinxue">@pinxue</a>
那知道 <a class="reference external" href="http://weibo.com/n/%E9%AB%98%E6%9D%BE__">@高松__</a>
送些VIP的票,pinxue则是从<a class="reference external" href="http://weibo.com/n/netwiser">@netwiser</a>
那认识的,他们还有Holly
Lee等是多年好友,而我认识netwiser(早肉身跑到加拿大,也是多个站的站长)是因为去年早期弄了个4s相关的小站,搞了个buzz账号五花马,关注了一票人,其间跟netwiser讨论了不少建站的经验。从netwiser到dreamsoft再到盛大创新院,真的是张比较神奇的网络,这难到就是传说中的社会化网络?</p>
<p>还有一票神秘的朋友在等着我呢,盛大,我来了。</p>
<p>9月1日是传统的入学的日子,宝宝今日入学幼儿园中班,爷爷奶奶一起送她去上学,老婆(老师)今天正式开学,而我则挑了这么个特殊的日子,在昨天匆匆忙忙告别Autodesk之后今日入职盛大创新院。今天全家出动,对我们可谓一个新的开始。</p>
<p>去年CSDN
SD大会碰巧坐<a class="reference external" href="http://weibo.com/n/%E4%BD%99%E5%B0%8F%E6%B3%A2">@余小波</a>旁,休息期间跟着余一起碰到了<a class="reference external" href="http://weibo.com/n/dreamsoft">@dreamsoft</a>
(人称老郭的创新院郭院长),当时我就震惊了,这居然是一院之长,太低调太Geek了吧,我毫无免疫力的瞬间成为老郭粉丝。</p>
<p>话说回来当时能去参加SD大会,完全是因为从<a class="reference external" href="http://weibo.com/n/pinxue">@pinxue</a>
那知道 <a class="reference external" href="http://weibo.com/n/%E9%AB%98%E6%9D%BE__">@高松__</a>
送些VIP的票,pinxue则是从<a class="reference external" href="http://weibo.com/n/netwiser">@netwiser</a>
那认识的,他们还有Holly
Lee等是多年好友,而我认识netwiser(早肉身跑到加拿大,也是多个站的站长)是因为去年早期弄了个4s相关的小站,搞了个buzz账号五花马,关注了一票人,其间跟netwiser讨论了不少建站的经验。从netwiser到dreamsoft再到盛大创新院,真的是张比较神奇的网络,这难到就是传说中的社会化网络?</p>
<p>还有一票神秘的朋友在等着我呢,盛大,我来了。</p>
弹指一挥间,四载欧特克2011-08-31T11:24:00+08:002011-08-31T11:24:00+08:00飞龙tag:feilong.me,2011-08-31:/2011/08/four-years-work-at-autodesk.html<p>弹指一挥间,我在欧特克(Autodesk)已工作了四年零两个月,今天是我在Autodesk的最后一天,看着下面这张工牌上的自己,不得不承认自己老了。</p>
<p><img alt="image0" class="aligncenter" src="/static/2011/08/pisla-li-191x300.jpg" style="width: 191px; height: 300px;" /></p>
<ul class="simple">
<li>四年前,就凭我那蹩脚的英语和烂水平,我根本没有想到我能够加入Autodesk这样的行业领军企业。</li>
<li>四年来,我很幸运的遇到了一个非常好的老板(Julie),也有赏识我的老板的老板,还有一个非常出色的团队,工作真的是非常的开心。在公司,身边尽是些牛X学校硕博毕业来的牛人,我在里头也就是个矮子(虽然算个头我还可以排在最前面),意识到有差距,所以我只好多花点精力向高手们学习了。这四年除了开心的工作外,业余没事也自己择腾些网站,虽然没有大成,但因此修炼了下功夫、认识了一票业内朋友,这四年是收获非常大的四年,唯一没有收获的是头发,头发是日渐稀少了!!!</li>
<li>四年后的今天,我最终选择了离开,我选择离开主要是基于我个人的兴趣和职业发展规划,我欲在(移动)互联网方向有所作为,赶上这一波发展浪潮,而Autodesk相对缺乏这样的机会,不过我负责任的说Autodesk仍是一家非常非常靠谱的软件公司,Autodesk在行业的地位无人能撼动,因此我仍然愿意推荐有兴趣和有能力的朋友加入Autodesk,即使我已经拿不到所谓的推荐费了。</li>
</ul>
<p>再见,Autodesk!</p>
<p>再见,Autodesk的朋友们!</p>
<p>弹指一挥间,我在欧特克(Autodesk)已工作了四年零两个月,今天是我在Autodesk的最后一天,看着下面这张工牌上的自己,不得不承认自己老了。</p>
<p><img alt="image0" class="aligncenter" src="/static/2011/08/pisla-li-191x300.jpg" style="width: 191px; height: 300px;" /></p>
<ul class="simple">
<li>四年前,就凭我那蹩脚的英语和烂水平,我根本没有想到我能够加入Autodesk这样的行业领军企业。</li>
<li>四年来,我很幸运的遇到了一个非常好的老板(Julie),也有赏识我的老板的老板,还有一个非常出色的团队,工作真的是非常的开心。在公司,身边尽是些牛X学校硕博毕业来的牛人,我在里头也就是个矮子(虽然算个头我还可以排在最前面),意识到有差距,所以我只好多花点精力向高手们学习了。这四年除了开心的工作外,业余没事也自己择腾些网站,虽然没有大成,但因此修炼了下功夫、认识了一票业内朋友,这四年是收获非常大的四年,唯一没有收获的是头发,头发是日渐稀少了!!!</li>
<li>四年后的今天,我最终选择了离开,我选择离开主要是基于我个人的兴趣和职业发展规划,我欲在(移动)互联网方向有所作为,赶上这一波发展浪潮,而Autodesk相对缺乏这样的机会,不过我负责任的说Autodesk仍是一家非常非常靠谱的软件公司,Autodesk在行业的地位无人能撼动,因此我仍然愿意推荐有兴趣和有能力的朋友加入Autodesk,即使我已经拿不到所谓的推荐费了。</li>
</ul>
<p>再见,Autodesk!</p>
<p>再见,Autodesk的朋友们!</p>
谈提问 - 如何有效的提问2011-08-30T17:56:00+08:002011-08-30T17:56:00+08:00飞龙tag:feilong.me,2011-08-30:/2011/08/how-to-ask-for-help.html<p>说明:接上篇“<a class="reference external" href="http://feilong.me/2011/08/talk-about-reading-books">谈读书</a>”,本篇博客也来自于昨天我在公司的分享。</p>
<p>自从芝麻问答上线以来,通过各种途径问我问题的人越来越多。同样是问我问题的,有人非常诚恳的虚心求教,同时也把问题描述得非常清楚;而另有个别朋友问我问题,不容我工作和思考,急催着我回答,反倒像我欠他似的。这样的情况我帮谁呢?我想每个人心中都有自己的答案。后者求助的方式非常不友好,我估计我下次还帮他的可能性会比较小了。</p>
<p>对于如何有效的提问,根据前人的一些总结材料(文章结尾有提供),结合我自己的一些经验,我精简为如下几个要点:</p>
<p><strong>提问前</strong></p>
<ul class="simple">
<li>请确认自己已经过努力思考,确实解决不了。</li>
<li>查找是否已有类似的问题存在,以尽量避免不必要的重复。</li>
</ul>
<p><strong>提问时</strong></p>
<ul class="simple">
<li>态度诚恳,虚心求教。</li>
<li>提供详细的信息,以便别人能够快速准确的帮助你解决问题。</li>
</ul>
<p><strong>提问后</strong></p>
<ul class="simple">
<li>尊重、感谢给你答案的人,特别是给你正确答案帮你解决了棘手问题的人。</li>
</ul>
<p>上面这部分其实只适合个人在社区求助,并不完全适合在公司用。从公司的角度来讲,有员工遇到问题时要的是最快的把问题解决掉,而最快解决问题的方式往往就是直接问最熟悉此问题的相关的人,而不是遇到问题的人自己在那里先研究择腾半天最后还是搞不定再去求助,对个人来讲这样不太有利于成长,但对公司来说往往这样简单粗暴的方式解决问题却是最有利的。</p>
<p>更多的关于如何智慧的提问,前人已有很详尽的总结,我不再多啰唆,大家可以去参考:<a class="reference external" href="http://wiki.woodpecker.org.cn/moin/AskForHelp">http</a><a class="reference external" href="http://wiki.woodpecker.org.cn/moin/AskForHelp">://</a><a class="reference external" href="http://wiki.woodpecker.org.cn/moin/AskForHelp">wiki …</a></p><p>说明:接上篇“<a class="reference external" href="http://feilong.me/2011/08/talk-about-reading-books">谈读书</a>”,本篇博客也来自于昨天我在公司的分享。</p>
<p>自从芝麻问答上线以来,通过各种途径问我问题的人越来越多。同样是问我问题的,有人非常诚恳的虚心求教,同时也把问题描述得非常清楚;而另有个别朋友问我问题,不容我工作和思考,急催着我回答,反倒像我欠他似的。这样的情况我帮谁呢?我想每个人心中都有自己的答案。后者求助的方式非常不友好,我估计我下次还帮他的可能性会比较小了。</p>
<p>对于如何有效的提问,根据前人的一些总结材料(文章结尾有提供),结合我自己的一些经验,我精简为如下几个要点:</p>
<p><strong>提问前</strong></p>
<ul class="simple">
<li>请确认自己已经过努力思考,确实解决不了。</li>
<li>查找是否已有类似的问题存在,以尽量避免不必要的重复。</li>
</ul>
<p><strong>提问时</strong></p>
<ul class="simple">
<li>态度诚恳,虚心求教。</li>
<li>提供详细的信息,以便别人能够快速准确的帮助你解决问题。</li>
</ul>
<p><strong>提问后</strong></p>
<ul class="simple">
<li>尊重、感谢给你答案的人,特别是给你正确答案帮你解决了棘手问题的人。</li>
</ul>
<p>上面这部分其实只适合个人在社区求助,并不完全适合在公司用。从公司的角度来讲,有员工遇到问题时要的是最快的把问题解决掉,而最快解决问题的方式往往就是直接问最熟悉此问题的相关的人,而不是遇到问题的人自己在那里先研究择腾半天最后还是搞不定再去求助,对个人来讲这样不太有利于成长,但对公司来说往往这样简单粗暴的方式解决问题却是最有利的。</p>
<p>更多的关于如何智慧的提问,前人已有很详尽的总结,我不再多啰唆,大家可以去参考:<a class="reference external" href="http://wiki.woodpecker.org.cn/moin/AskForHelp">http</a><a class="reference external" href="http://wiki.woodpecker.org.cn/moin/AskForHelp">://</a><a class="reference external" href="http://wiki.woodpecker.org.cn/moin/AskForHelp">wiki.woodpecker.org.cn/moin/AskForHelp</a></p>
谈读书 - 多读书,读好书2011-08-30T16:36:00+08:002011-08-30T16:36:00+08:00飞龙tag:feilong.me,2011-08-30:/2011/08/talk-about-reading-books.html<p>说明:此博客源于我昨天在公司做的一次分享,整个分享虽然有PPT和录音,但不便于完全公开,我将将其中的部分内容整理后以博客的形式分享给大家,谈读书是其中之一。</p>
<p>微博有看到这么一篇微博:假如把你放逐到山洞里,吃穿住不愁,笔墨纸砚各种书籍都有,但是没有网络,没有微博、电话、电视、手机、短信,跟外界唯一的联系是可以写信,
三年一亿,你干吗? <a class="reference external" href="http://weibo.com/1134796120/xkXPF28dI">http://weibo.com/1134796120/xkXPF28dI</a></p>
<p><img alt="image0" class="size-full wp-image-581 aligncenter" src="/static/2011/08/shandong.jpg" style="width: 400px; height: 257px;" /></p>
<p>我的回答是:当然干,有书足矣。</p>
<p>我很喜欢读书,即使现在有了Kindle,我仍然不停的买入新的纸质书籍,我喜欢在Kindle上阅读,更喜欢闻着纸书的书香来阅读。床上、地铁上和马桶上都是我读书的最佳场所,特别是后两种,怎么可能会没有书陪伴?</p>
<p>我家离办公室很远,单趟光地铁上就要1个小时,马上还会更远一些,老婆看我辛苦,考虑给我在小区业主论坛上找找看是不是有拼车直接到的(干脆给买个车多好),我一口予以否决,原因很简单,拼车是坐小汽车,上班路上我将无法象坐铁上那样能享受阅读了,这怎么受得了?有人看到这里可能会骂我装13了,其实我也是这么觉得的,不过有这些闲话又有什么关系呢 …</p><p>说明:此博客源于我昨天在公司做的一次分享,整个分享虽然有PPT和录音,但不便于完全公开,我将将其中的部分内容整理后以博客的形式分享给大家,谈读书是其中之一。</p>
<p>微博有看到这么一篇微博:假如把你放逐到山洞里,吃穿住不愁,笔墨纸砚各种书籍都有,但是没有网络,没有微博、电话、电视、手机、短信,跟外界唯一的联系是可以写信,
三年一亿,你干吗? <a class="reference external" href="http://weibo.com/1134796120/xkXPF28dI">http://weibo.com/1134796120/xkXPF28dI</a></p>
<p><img alt="image0" class="size-full wp-image-581 aligncenter" src="/static/2011/08/shandong.jpg" style="width: 400px; height: 257px;" /></p>
<p>我的回答是:当然干,有书足矣。</p>
<p>我很喜欢读书,即使现在有了Kindle,我仍然不停的买入新的纸质书籍,我喜欢在Kindle上阅读,更喜欢闻着纸书的书香来阅读。床上、地铁上和马桶上都是我读书的最佳场所,特别是后两种,怎么可能会没有书陪伴?</p>
<p>我家离办公室很远,单趟光地铁上就要1个小时,马上还会更远一些,老婆看我辛苦,考虑给我在小区业主论坛上找找看是不是有拼车直接到的(干脆给买个车多好),我一口予以否决,原因很简单,拼车是坐小汽车,上班路上我将无法象坐铁上那样能享受阅读了,这怎么受得了?有人看到这里可能会骂我装13了,其实我也是这么觉得的,不过有这些闲话又有什么关系呢?我真的能看书啊!</p>
<p>多读书的同时,我提倡尽量读好书,读精品书籍。虽然我们人类大脑的潜在容量几乎没有限度,据说可以装下50亿本书,但我们的寿命是有限度的,我们花在读书上的时间更是有限的,而读过之后还能记下来的东西更是少得可怜,在这种情况下为什么不集中精力去读那些好书呢?当然我这里说的好书不一定是时下热门的书籍,但一定是经得过时间考验的书。</p>
<p>下面列了一些我最近看过或正在看的书,主要是IT技术和相关的人文书籍,作为技术类书籍,有些已经可以称得上古董了。我可以负责任的说,这些都是非常好的书籍,我这里也算是给大家推荐书籍了。为了避免大家说我是个书托,我就不提供相应书籍的购买链接了,大家要买自己去搜好了。</p>
<p><img alt="image1" class="alignnone size-full wp-image-596" src="/static/2011/08/good-books.jpg" style="width: 596px; height: 302px;" /></p>
<p>为什么这里面会有一本经济学的书籍呢?请看下面这段摘自《软件随想录》(More
Joel on Software)中的话:</p>
<blockquote>
Why should CS majors learn economic? Because a programmer who
understands the fundamentals of business is going to be a more
valuable programmer, to a business, than a programmer who doesn’t. That’s all there is to it. I can’t tell you how many times I’ve been frustrated
by programmers with crazy ideas that make sense in code but don’t make sense in capitalism. If you understand this stuff, you’re a more valuable
programmer, and you’ll get rewarded for it, for reasons that you’ll
also learn in microeconomics.</blockquote>
<p>所以我在这里强烈推荐大家去读点经济学书籍,我自己也在重新学习经济学中。</p>
<p>最后附上一段非常经典的一分钟视频“李嘉诚劝读书”,视频很短,但字字珠玑,相信对你会有所触动。</p>
<p>视频地址:<a class="reference external" href="http://v.youku.com/v_show/id_XMjgxNTY0MzY4.html">http://v.youku.com/v_show/id_XMjgxNTY0MzY4.html</a></p>
<p>转载请注明出处:<a class="reference external" href="http://feilong.me/2011/08/talk-about-reading-books">http://feilong.me/2011/08/talk-about-reading-books</a></p>
Python web开发吐槽2011-08-03T13:30:00+08:002011-08-03T13:30:00+08:00飞龙tag:feilong.me,2011-08-03:/2011/08/talk-about-python-web-in-july-python-salon.html<p>说来惭愧,我用Python也有近5年了,但2011年7月上海Python聚会还是我第一次参与Python线下活动。第一次去,多少拿点东西去分享下吧,因此我以我的业余水平跑去吐槽吐槽了下Python的web开发。</p>
<p>此次聚会因为有沈崴沈游侠到场,来膜拜沈游侠的人很多,我也是其中之一,我的吐槽议题只是起个头的,录音中大家也可以听到很多Python牛人吐槽的声音。</p>
<p>下面为我在2011年7月上海Python聚会上吐槽Python web开发的录音和PPT材料。</p>
<p><a class="reference external" href="http://dlc3.sdo.com/FTP/CASMI/96423216/162768713/007M_110731_1353.MP3">Python
web开发吐槽实况录音</a></p>
<p><a class="reference external" href="http://www.slideshare.net/FelinxLee/python-web">Python
web开发吐槽PPT</a></p>
<p>说来惭愧,我用Python也有近5年了,但2011年7月上海Python聚会还是我第一次参与Python线下活动。第一次去,多少拿点东西去分享下吧,因此我以我的业余水平跑去吐槽吐槽了下Python的web开发。</p>
<p>此次聚会因为有沈崴沈游侠到场,来膜拜沈游侠的人很多,我也是其中之一,我的吐槽议题只是起个头的,录音中大家也可以听到很多Python牛人吐槽的声音。</p>
<p>下面为我在2011年7月上海Python聚会上吐槽Python web开发的录音和PPT材料。</p>
<p><a class="reference external" href="http://dlc3.sdo.com/FTP/CASMI/96423216/162768713/007M_110731_1353.MP3">Python
web开发吐槽实况录音</a></p>
<p><a class="reference external" href="http://www.slideshare.net/FelinxLee/python-web">Python
web开发吐槽PPT</a></p>
浅析轮询(Polling)和推送(Long-Polling)服务2011-07-13T13:42:00+08:002011-07-13T13:42:00+08:00飞龙tag:feilong.me,2011-07-13:/2011/07/talk-about-polling-and-long-polling.html<p>说明:此博客源自我在python-cn邮件群组中对网友关于Comet的问题的回答,特整理下供更多需要了解的人参考。</p>
<ol class="arabic simple">
<li>轮询(Polling)是指不管服务器端有没有更新,客户端(通常是指浏览器)都定时的发送请求进行查询,轮询的结果可能是服务器端有新的更新过来,也可能什么也没有,只是返回个空的信息。不管结果如何,客户端处理完后到下一个定时时间点将继续下一轮的轮询。</li>
<li>推送或叫长连接(Long-Polling)的服务其客户端是不做轮询的,客户端在发起一次请求后立即挂起,一直到服务器端有更新的时候,服务器才会主动推送信息到客户端。 在服务器端有更新并推送信息过来之前这个周期内,客户端不会有新的多余的请求发生,服务器端对此客户端也啥都不用干,只保留最基本的连接信息,一旦服务器有更新将推送给客户端,客户端将相应的做出处理,处理完后再重新发起下一轮请求。</li>
</ol>
<p>举个例子说明下就很清楚了:</p>
<ol class="arabic simple">
<li>轮询模式,假设是客户端每2秒轮询一次,那么客户端每2秒就会发送一次请求,相应的服务器端每2秒就要响应这个客户端的一次请求。而实际上服务器端可能1秒钟后就有更新,也可能1分钟后才有更新。对于1秒钟就有更新的,客户端至少会有1秒钟的延时;而1分钟后才有更新的,只有最后一次查询有意义,这一分钟内的轮询其实都是没有必要的,服务器端和客户端均有资源的浪费。</li>
<li>推送模式,客户端发送一次请求后马上挂起等待服务器端响应,可能1秒,也可能10秒钟,也可能1分钟。如果服务器端是1秒就有更新,那么到1秒钟时客户端马上就收到更新了,如果是1分钟才有更新,那么整个一分钟客户端也只请求一次,服务器也只会相应一次 …</li></ol><p>说明:此博客源自我在python-cn邮件群组中对网友关于Comet的问题的回答,特整理下供更多需要了解的人参考。</p>
<ol class="arabic simple">
<li>轮询(Polling)是指不管服务器端有没有更新,客户端(通常是指浏览器)都定时的发送请求进行查询,轮询的结果可能是服务器端有新的更新过来,也可能什么也没有,只是返回个空的信息。不管结果如何,客户端处理完后到下一个定时时间点将继续下一轮的轮询。</li>
<li>推送或叫长连接(Long-Polling)的服务其客户端是不做轮询的,客户端在发起一次请求后立即挂起,一直到服务器端有更新的时候,服务器才会主动推送信息到客户端。 在服务器端有更新并推送信息过来之前这个周期内,客户端不会有新的多余的请求发生,服务器端对此客户端也啥都不用干,只保留最基本的连接信息,一旦服务器有更新将推送给客户端,客户端将相应的做出处理,处理完后再重新发起下一轮请求。</li>
</ol>
<p>举个例子说明下就很清楚了:</p>
<ol class="arabic simple">
<li>轮询模式,假设是客户端每2秒轮询一次,那么客户端每2秒就会发送一次请求,相应的服务器端每2秒就要响应这个客户端的一次请求。而实际上服务器端可能1秒钟后就有更新,也可能1分钟后才有更新。对于1秒钟就有更新的,客户端至少会有1秒钟的延时;而1分钟后才有更新的,只有最后一次查询有意义,这一分钟内的轮询其实都是没有必要的,服务器端和客户端均有资源的浪费。</li>
<li>推送模式,客户端发送一次请求后马上挂起等待服务器端响应,可能1秒,也可能10秒钟,也可能1分钟。如果服务器端是1秒就有更新,那么到1秒钟时客户端马上就收到更新了,如果是1分钟才有更新,那么整个一分钟客户端也只请求一次,服务器也只会相应一次,这个跟轮询的区别是不是已经很清楚了。</li>
</ol>
tornadoweb.cn现提供Tornado中译文档2011-06-20T15:14:00+08:002011-06-20T15:14:00+08:00飞龙tag:feilong.me,2011-06-20:/2011/06/tornadoweb-cn-documentation.html<p>2011/07/06最新补充:tornado发布2.0后文档组织有较大更新,现 <a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn</a>
的子站 <a class="reference external" href="http://en.tornadoweb.cn/">http://en.tornadoweb.cn</a>
提供原始文档的完整镜像,跟<a class="reference external" href="http://tornado.org/">tornado.org</a>同步,不再是本地的一个版本,cn站点首页提供的文档链接也已更新。</p>
<p>===</p>
<p><a class="reference external" href="http://www.tornadoweb.org">tornadoweb.org</a>的镜像站点<a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn</a>(关于此镜像的由来另见:<a class="reference external" href="http://feilong.me/2011/05/tornadoweb-cn-mirror">发布Tornado镜像站点tornadoweb.cn</a>)现提供Tornado中译文档供参考,新的网站目录结构如下:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn/</a> 中译首页</li>
<li><a class="reference external" href="http://www.tornadoweb.cn/documentation">http://www.tornadoweb.cn/documentation</a> 中译Tornado文档</li>
<li><a class="reference external" href="http://www.tornadoweb.cn/en">http://www.tornadoweb.cn/en …</a></li></ul><p>2011/07/06最新补充:tornado发布2.0后文档组织有较大更新,现 <a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn</a>
的子站 <a class="reference external" href="http://en.tornadoweb.cn/">http://en.tornadoweb.cn</a>
提供原始文档的完整镜像,跟<a class="reference external" href="http://tornado.org/">tornado.org</a>同步,不再是本地的一个版本,cn站点首页提供的文档链接也已更新。</p>
<p>===</p>
<p><a class="reference external" href="http://www.tornadoweb.org">tornadoweb.org</a>的镜像站点<a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn</a>(关于此镜像的由来另见:<a class="reference external" href="http://feilong.me/2011/05/tornadoweb-cn-mirror">发布Tornado镜像站点tornadoweb.cn</a>)现提供Tornado中译文档供参考,新的网站目录结构如下:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn/</a> 中译首页</li>
<li><a class="reference external" href="http://www.tornadoweb.cn/documentation">http://www.tornadoweb.cn/documentation</a> 中译Tornado文档</li>
<li><a class="reference external" href="http://www.tornadoweb.cn/en">http://www.tornadoweb.cn/en</a> 原版首页镜像</li>
<li><a class="reference external" href="http://www.tornadoweb.cn/en/documentation">http://www.tornadoweb.cn/en/documentation</a> 原版文档镜像</li>
</ul>
<p>该中文文档的大部分翻译工作由 <a class="reference external" href="http://zys-free.com/">邹业盛</a>
完成,后期的增修和编排由 <a class="reference external" href="http://ducktypist.com/">gastlygem</a> 完成。
译文版权归原作者和译者所有,翻译原稿见
<a class="reference external" href="http://github.com/breezemind/tornado/tree/master/website/templates/cn">Tornado中文版文档</a>。
<a class="reference external" href="http://www.tornadoweb.cn%20">http://www.tornadoweb.cn</a>由
<a class="reference external" href="../">飞龙</a> 筹划并赞助空间和域名。</p>
<p>大家发现有待优化的地方,可以参与进来进行改进,翻译的文件在
<a class="reference external" href="https://github.com/breezemind/tornado/tree/master/website/templates/cn">https://github.com/breezemind/tornado/tree/master/website/templates/cn</a>,给发我一个pull
request即可。</p>
nginx反向代理配置(附:tornadoweb.cn的nginx配置)2011-06-11T11:41:00+08:002011-06-11T11:41:00+08:00飞龙tag:feilong.me,2011-06-11:/2011/06/nginx-reverse-proxy.html<p>GAE的Hosting站点
<a class="reference external" href="http://appspot.com/">appspot.com</a>在国内被墙,因此架设在GAE上的运用没法直接访问,需要曲线救国,其中一招比较有效的方式即是通过nginx反向代理来实现,不过这个要求你在国外有一个可用的nginx。下面以<a class="reference external" href="http://www.tornadoweb.cn">tornadoweb.cn</a>为例讲述如何用nginx配置反向代理(注:tornadoweb.cn为<a class="reference external" href="http://www.tornadoweb.org/">tornadoweb.org</a>的镜像站点,原站就是在GAE上,因此国内无法直接访问)。关于nginx的基本配置部分请参考我在poweredsites上的博客<a class="reference external" href="http://blog.poweredsites.org/entry/how-to-setup-nginx">how-to-setup-nginx</a>,本文只讨论如何配置tornadoweb.cn这个站点,配置说明详见配置中的注释。</p>
<pre class="literal-block">
server {
# 监听80端口,通常可以省略。
listen 80;
# 要配置的站点域名,即用来曲线访问GAE上的原站点的域名。
server_name www.tornadoweb.cn;
# Ben老大要求tornadoweb.cn有说明是镜像站点以区别于原站tornadoweb.org,
# 因此我走巧将头上的LOGO采用修改过的本地文件,在原logo上加了mirror的声明
location /static/tornado.png {
# LOGO文件tornado.png所在文件夹目录
root /mnt/ebs …</pre><p>GAE的Hosting站点
<a class="reference external" href="http://appspot.com/">appspot.com</a>在国内被墙,因此架设在GAE上的运用没法直接访问,需要曲线救国,其中一招比较有效的方式即是通过nginx反向代理来实现,不过这个要求你在国外有一个可用的nginx。下面以<a class="reference external" href="http://www.tornadoweb.cn">tornadoweb.cn</a>为例讲述如何用nginx配置反向代理(注:tornadoweb.cn为<a class="reference external" href="http://www.tornadoweb.org/">tornadoweb.org</a>的镜像站点,原站就是在GAE上,因此国内无法直接访问)。关于nginx的基本配置部分请参考我在poweredsites上的博客<a class="reference external" href="http://blog.poweredsites.org/entry/how-to-setup-nginx">how-to-setup-nginx</a>,本文只讨论如何配置tornadoweb.cn这个站点,配置说明详见配置中的注释。</p>
<pre class="literal-block">
server {
# 监听80端口,通常可以省略。
listen 80;
# 要配置的站点域名,即用来曲线访问GAE上的原站点的域名。
server_name www.tornadoweb.cn;
# Ben老大要求tornadoweb.cn有说明是镜像站点以区别于原站tornadoweb.org,
# 因此我走巧将头上的LOGO采用修改过的本地文件,在原logo上加了mirror的声明
location /static/tornado.png {
# LOGO文件tornado.png所在文件夹目录
root /mnt/ebs/sites/tornadoweb;
}
location / {
# 配置反向代理到 www.tornadoweb.org,对于没有绑定域名的GAE运用来说,会是http://python-tornado.appspot.com这样的。
proxy_pass http://www.tornadoweb.org;
# 关闭重定向跳转
proxy_redirect off;
# 转发IP等HTTP头信息
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# 下面几个是将www.tornadoweb.com.cn也跳转到www.tornadoweb.cn,并且将域名根目录tornadoweb.cn这样的访问也跳转到www下,
# 这个反之亦然(现在多是这种,即www跳转到域名根目录)。
server {
server_name tornadoweb.com.cn;
rewrite ^(.*)$ http://www.tornadoweb.cn$1 permanent;
}
server {
server_name www.tornadoweb.com.cn;
rewrite ^(.*)$ http://www.tornadoweb.cn$1 permanent;
}
server {
server_name tornadoweb.cn;
rewrite ^(.*)$ http://www.tornadoweb.cn$1 permanent;
}
</pre>
<p>配置好后reload/restart一下nginx就妥了,本例的结果即是访问tornadoweb.cn将看到tornadoweb.org一样网站,除了采用了本地文件的那个LOGO不同外。</p>
[ZT]各大搜索引擎的网站登录入口地址大全2011-05-23T17:41:00+08:002011-05-23T17:41:00+08:00飞龙tag:feilong.me,2011-05-23:/2011/05/where-to-submit-sites-to-search-engines.html<div class="line-block">
<div class="line"><strong>网站建设</strong>、<strong>网站推广</strong>必不可少的步骤之一<strong>,各大搜索引擎网站登录入口</strong>:</div>
<div class="line"><a class="reference external" href="http://www.baidu.com/search/url_submit.html">百度网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.google.com/addurl/">Google网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://search.help.cn.yahoo.com/h4_4.html">Yahoo网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://cn.bing.com/webmaster/SubmitSitePage.aspx">Bing网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.dmoz.com/World/Chinese_Simplified">Dmoz网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.coodir.com/accounts/addsite.asp">Coodir网站目录登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.alexa.com/help/webmasters">Alexa网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.sogou.com/feedback/urlfeedback.php">搜狗网站收录提交入口</a></div>
<div class="line"><a class="reference external" href="http://www.soso.com/help/usb/urlsubmit.shtml">Soso网站收录提交入口</a></div>
<div class="line"><a class="reference external" href="http://tellbot.youdao.com/report">有道搜索网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://indexed.webmasterhome.cn/">搜索引擎收录查询</a></div>
<div class="line"><a class="reference external" href="http://ads.zhongsou.com/register/page.jsp">中国搜索网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.freewebsubmission.com/">Freewebsubmission.com
搜索引擎批量提交</a></div>
</div>
<p>因为这个会我经常用到,每次老是跑去搜索,纯转帖+mark一记,原帖见:<a class="reference external" href="http://www.webmasterhome.cn/seo/AddUrl.asp">http://www.webmasterhome.cn/seo/AddUrl.asp</a></p>
<div class="line-block">
<div class="line"><strong>网站建设</strong>、<strong>网站推广</strong>必不可少的步骤之一<strong>,各大搜索引擎网站登录入口</strong>:</div>
<div class="line"><a class="reference external" href="http://www.baidu.com/search/url_submit.html">百度网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.google.com/addurl/">Google网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://search.help.cn.yahoo.com/h4_4.html">Yahoo网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://cn.bing.com/webmaster/SubmitSitePage.aspx">Bing网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.dmoz.com/World/Chinese_Simplified">Dmoz网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.coodir.com/accounts/addsite.asp">Coodir网站目录登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.alexa.com/help/webmasters">Alexa网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.sogou.com/feedback/urlfeedback.php">搜狗网站收录提交入口</a></div>
<div class="line"><a class="reference external" href="http://www.soso.com/help/usb/urlsubmit.shtml">Soso网站收录提交入口</a></div>
<div class="line"><a class="reference external" href="http://tellbot.youdao.com/report">有道搜索网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://indexed.webmasterhome.cn/">搜索引擎收录查询</a></div>
<div class="line"><a class="reference external" href="http://ads.zhongsou.com/register/page.jsp">中国搜索网站登录入口</a></div>
<div class="line"><a class="reference external" href="http://www.freewebsubmission.com/">Freewebsubmission.com
搜索引擎批量提交</a></div>
</div>
<p>因为这个会我经常用到,每次老是跑去搜索,纯转帖+mark一记,原帖见:<a class="reference external" href="http://www.webmasterhome.cn/seo/AddUrl.asp">http://www.webmasterhome.cn/seo/AddUrl.asp</a></p>
发布Tornado镜像站点tornadoweb.cn2011-05-19T15:06:00+08:002011-05-19T15:06:00+08:00飞龙tag:feilong.me,2011-05-19:/2010/05/tornadoweb-cn-mirror.html<p>鉴于<a class="reference external" href="http://www.tornadoweb.org">Tornado官网</a>架设在GAE上,而GAE在国内被墙,如果不爬墙大家访问不了Tornado官网,这个让很多国内Tornado用户不爽,也影响了Tornado在国内的推广。而我手头一直持有<a class="reference external" href="http://www.tornadoweb.cn">tornadoweb.cn</a>和tornadoweb.com.cn两个域名,之前是想开发个Tornado的中文站的,但在目前闲置的情况下,还不如先做一个官方网站的镜像,故今天特配置了一下我EC2上的nginx,做了一个Tornado官方网站的镜像站点<a class="reference external" href="http://www.tornadoweb.cn">tornadoweb.cn</a>,以造福国内Tornado用户,以后国内用户就可以直接通过<a class="reference external" href="http://www.tornadoweb.cn/">tornadoweb.cn</a>查阅Tornado的文档了。</p>
<p>此举已致信Tornado的Ben:</p>
<p>Hi, Ben,</p>
<p>I have tried to create a mirror
site(<a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn</a>, just
proxy the origin content) of <a class="reference external" href="http://tornadoweb.org/">tornadoweb.org</a>
for Chinese …</p><p>鉴于<a class="reference external" href="http://www.tornadoweb.org">Tornado官网</a>架设在GAE上,而GAE在国内被墙,如果不爬墙大家访问不了Tornado官网,这个让很多国内Tornado用户不爽,也影响了Tornado在国内的推广。而我手头一直持有<a class="reference external" href="http://www.tornadoweb.cn">tornadoweb.cn</a>和tornadoweb.com.cn两个域名,之前是想开发个Tornado的中文站的,但在目前闲置的情况下,还不如先做一个官方网站的镜像,故今天特配置了一下我EC2上的nginx,做了一个Tornado官方网站的镜像站点<a class="reference external" href="http://www.tornadoweb.cn">tornadoweb.cn</a>,以造福国内Tornado用户,以后国内用户就可以直接通过<a class="reference external" href="http://www.tornadoweb.cn/">tornadoweb.cn</a>查阅Tornado的文档了。</p>
<p>此举已致信Tornado的Ben:</p>
<p>Hi, Ben,</p>
<p>I have tried to create a mirror
site(<a class="reference external" href="http://www.tornadoweb.cn/">http://www.tornadoweb.cn</a>, just
proxy the origin content) of <a class="reference external" href="http://tornadoweb.org/">tornadoweb.org</a>
for Chinese because <a class="reference external" href="http://tornadoweb.org/">tornadoweb.org</a> is
blocked by GFW in China, so Chinese guys can not view Tornado
documentation online if they do not use any VPNs.</p>
<p>Can I do that? If it is ok, I would like to announce this site to
Tornado uses in China, it's a good news for them really, thanks a lot.</p>
<p>Ben很快回复了,但他希望最好能在头上说明下这是原站的镜像:</p>
<p>Yeah, I think that's fine. Maybe just add a disclaimer at the top of
the home page that this is a mirror and the official home page is
<a class="reference external" href="http://tornadoweb.org/">tornadoweb.org</a>.</p>
<p>因此,我接着就把tornado的logo文件代理到一个本地新制作的文件,在原logo上加上了是镜像的备注信息(A
mirror of tornadoweb.org),再次给Ben去了封信,Ben立马就回了。</p>
<p>Yeah, looks good.</p>
<p>OK,此事搞定!</p>
<p>呱唧呱唧,大家还不给飞龙鼓掌:)</p>
<p>转载请注明出处:<a class="reference external" href="http://feilong.me/2011/05/tornadoweb-cn-mirror">http://feilong.me/2011/05/tornadoweb-cn-mirror</a></p>
JustAJoke长期招聘Python初级工程师(内附薪资)2011-05-06T08:51:00+08:002011-05-06T08:51:00+08:00飞龙tag:feilong.me,2011-05-06:/2011/05/just-a-joke-python-jobs.html<p>JustAJoke研发团队主要从事娱乐浮云业务,因业务发展迅猛,现长期招聘靠谱Python初级技术人员,要求如下:</p>
<ol class="arabic simple">
<li>精通Unix & Linux & MacOS,要求不会Windows。</li>
<li>精通Nginx、Apache、Postfix等各种服务器软件的配置和优化,能够根据服务器错误日志快速诊断定位服务器故障,有大型网站运维经验者优先。</li>
<li>精通Python、PHP、Java、Ruby语言中的至少四种,掌握Erlang、Go、Scala、SmallTalk语言的优先,Lisp尤佳。</li>
<li>精通Tornado、Django、Pylons、Flask等常用Python开发框架,熟悉Spring、Hibernate、Structs、Zend、Yii、Symfony等框架优先,ROR尤佳。</li>
<li>精通MySQL、PostgreSQL、Oracle等关系数据库和数据库优化技术,深入研究MongoDB、Couchdb、Redis等NoSQL
数据库者优先。</li>
<li>精通JavaScript、CSS、jQuery、jQueryUI等前端技术,能够写出漂亮的兼容IE5-IE9、Firefox、Chrome、Safari的JS和CSS代码。</li>
<li>精通Photoshop …</li></ol><p>JustAJoke研发团队主要从事娱乐浮云业务,因业务发展迅猛,现长期招聘靠谱Python初级技术人员,要求如下:</p>
<ol class="arabic simple">
<li>精通Unix & Linux & MacOS,要求不会Windows。</li>
<li>精通Nginx、Apache、Postfix等各种服务器软件的配置和优化,能够根据服务器错误日志快速诊断定位服务器故障,有大型网站运维经验者优先。</li>
<li>精通Python、PHP、Java、Ruby语言中的至少四种,掌握Erlang、Go、Scala、SmallTalk语言的优先,Lisp尤佳。</li>
<li>精通Tornado、Django、Pylons、Flask等常用Python开发框架,熟悉Spring、Hibernate、Structs、Zend、Yii、Symfony等框架优先,ROR尤佳。</li>
<li>精通MySQL、PostgreSQL、Oracle等关系数据库和数据库优化技术,深入研究MongoDB、Couchdb、Redis等NoSQL
数据库者优先。</li>
<li>精通JavaScript、CSS、jQuery、jQueryUI等前端技术,能够写出漂亮的兼容IE5-IE9、Firefox、Chrome、Safari的JS和CSS代码。</li>
<li>精通Photoshop、Fireworks、Dreamweaver,有线上的PS作品优先(请提供你的作品链接)。</li>
<li>精通Git、Hg、SVN、P4等代码管理工具,参与过开源项目的开发,请提供开源项目代码仓库链接。</li>
<li>超强的自学能力、积极的工作心态、良好的团队合作精神,能够承受较强的工作压力和长期出差在外。</li>
<li>最后要求熟谙各种娱乐花边新闻、各种炒作技术。</li>
</ol>
<div class="line-block">
<div class="line">公司地址:我朝某个犄角旮旯</div>
<div class="line">薪资水平:视个人能力5k-2000k</div>
<div class="line">联系方式:<a class="reference external" href="mailto:hr@JustAJoke.com">hr@JustAJoke.com</a></div>
</div>
用Supervisord管理Python进程2011-03-29T11:51:00+08:002011-03-29T11:51:00+08:00飞龙tag:feilong.me,2011-03-29:/2011/03/monitor-processes-with-supervisord.html<p>Supervisord是用Python实现的一款非常实用的进程管理工具,类似于<a class="reference external" href="http://mmonit.com/monit/">monit</a>(关于monit见我的博客:<a class="reference external" href="http://feilong.me/2011/02/monitor-core-processes-with-monit">用monit监控系统关键进程</a>),monit和supervisord的一个比较大的差异是supervisord管理的进程必须由supervisord来启动,monit可以管理已经在运行的程序;supervisord还要求管理的程序是非daemon程序,supervisord会帮你把它转成daemon程序,因此如果用supervisord来管理nginx的话,必须在nginx的配置文件里添加一行设置daemon
off让nginx以非daemon方式启动。</p>
<div class="section" id="supervisord">
<h2>Supervisord安装</h2>
<p>Supervisord可以通过<tt class="docutils literal">sudo easy_install supervisor</tt>安装,当然也可以通过<a class="reference external" href="http://supervisord.org/">Supervisord官网</a>下载后setup.py
install安装。</p>
</div>
<div class="section" id="id1">
<h2>Supervisord配置</h2>
<p>Supervisord默认的配置文件路径为/etc/supervisord.conf,通过文本编辑器修改这个文件,下面是一个示例的配置文件:</p>
<pre class="literal-block">
;/etc/supervisord.conf
[unix_http_server]
file = /var/run/supervisor.sock
chmod = 0777
chown= root:felinx
[inet_http_server]
# Web管理界面设定
port=9001
username = admin …</pre></div><p>Supervisord是用Python实现的一款非常实用的进程管理工具,类似于<a class="reference external" href="http://mmonit.com/monit/">monit</a>(关于monit见我的博客:<a class="reference external" href="http://feilong.me/2011/02/monitor-core-processes-with-monit">用monit监控系统关键进程</a>),monit和supervisord的一个比较大的差异是supervisord管理的进程必须由supervisord来启动,monit可以管理已经在运行的程序;supervisord还要求管理的程序是非daemon程序,supervisord会帮你把它转成daemon程序,因此如果用supervisord来管理nginx的话,必须在nginx的配置文件里添加一行设置daemon
off让nginx以非daemon方式启动。</p>
<div class="section" id="supervisord">
<h2>Supervisord安装</h2>
<p>Supervisord可以通过<tt class="docutils literal">sudo easy_install supervisor</tt>安装,当然也可以通过<a class="reference external" href="http://supervisord.org/">Supervisord官网</a>下载后setup.py
install安装。</p>
</div>
<div class="section" id="id1">
<h2>Supervisord配置</h2>
<p>Supervisord默认的配置文件路径为/etc/supervisord.conf,通过文本编辑器修改这个文件,下面是一个示例的配置文件:</p>
<pre class="literal-block">
;/etc/supervisord.conf
[unix_http_server]
file = /var/run/supervisor.sock
chmod = 0777
chown= root:felinx
[inet_http_server]
# Web管理界面设定
port=9001
username = admin
password = yourpassword
[supervisorctl]
; 必须和'unix_http_server'里面的设定匹配
serverurl = unix:///var/run/supervisord.sock
[supervisord]
logfile=/var/log/supervisord/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=true ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
user=root ; (default is current user, required if root)
childlogdir=/var/log/supervisord/ ; ('AUTO' child log dir, default $TEMP)
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
; 管理的单个进程的配置,可以添加多个program
[program:chatdemon]
command=python /home/felinx/demos/chat/chatdemo.py
autostart = true
startsecs = 5
user = felinx
redirect_stderr = true
;这对这个program的log的配置,上面的logfile_maxbytes是supervisord本身的log配置
stdout_logfile_maxbytes = 20MB
stdoiut_logfile_backups = 20
stdout_logfile = /var/log/supervisord/chatdemo.log
; 配置一组进程,对于类似的program可以通过这种方式添加,避免手工一个个添加
[program:groupworker]
command=python /home/felinx/demos/groupworker/worker.py
numprocs=24
process_name=%(program_name)s_%(process_num)02d
autostart = true
startsecs = 5
user = felinx
redirect_stderr = true
stdout_logfile = /var/log/supervisord/groupworker.log
</pre>
</div>
<div class="section" id="id2">
<h2>Supervisord管理</h2>
<p>Supervisord安装完成后有两个可用的命令行supervisor和supervisorctl,命令使用解释如下:</p>
<ul class="simple">
<li>supervisord,初始启动Supervisord,启动、管理配置中设置的进程。</li>
<li>supervisorctl stop
programxxx,停止某一个进程(programxxx),programxxx为<tt class="docutils literal">[program:chatdemon]</tt>里配置的值,这个示例就是chatdemon。</li>
<li>supervisorctl start programxxx,启动某个进程</li>
<li>supervisorctl restart programxxx,重启某个进程</li>
<li>supervisorctl stop groupworker:
,重启所有属于名为groupworker这个分组的进程(start,restart同理)</li>
<li>supervisorctl stop
all,停止全部进程,注:start、restart、stop都不会载入最新的配置文件。</li>
<li>supervisorctl
reload,载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程。</li>
<li>supervisorctl
update,根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启。</li>
<li>注意:显示用stop停止掉的进程,用reload或者update都不会自动重启。</li>
</ul>
</div>
Pycon2011精彩视频分享2011-03-21T10:58:00+08:002011-03-21T10:58:00+08:00飞龙tag:feilong.me,2011-03-21:/2011/03/pycon2011-videos-sharing.html<p>Python大会上的精彩视频,这些视频很大而且在墙外,因此我用本站的服务器下了下来,然后转到了我国内的服务器,特分享给大家。</p>
<ul class="simple">
<li><a class="reference external" href="http://goo.gl/KvA5G">Pycon-PyCon2011AnIntroductionToTornado277.m4v</a>
献给Tornado爱好者,视频开头有一些垃圾时间,可以忽略。</li>
<li><a class="reference external" href="http://goo.gl/O94np">How Dropbox Did It and How Python Helped</a>
Python在Dropbox的运用。</li>
<li><a class="reference external" href="http://goo.gl/W759t">Using Coroutines to Create Efficient, High-Concurrency Web
Applications</a> 介绍Python协程的。</li>
<li><a class="reference external" href="http://goo.gl/95PtV">Advanced Network Architectures With ZeroMQ</a></li>
<li>待补充...,欢迎大家推荐Pycon2011视频源。</li>
</ul>
<p>Python大会上的精彩视频,这些视频很大而且在墙外,因此我用本站的服务器下了下来,然后转到了我国内的服务器,特分享给大家。</p>
<ul class="simple">
<li><a class="reference external" href="http://goo.gl/KvA5G">Pycon-PyCon2011AnIntroductionToTornado277.m4v</a>
献给Tornado爱好者,视频开头有一些垃圾时间,可以忽略。</li>
<li><a class="reference external" href="http://goo.gl/O94np">How Dropbox Did It and How Python Helped</a>
Python在Dropbox的运用。</li>
<li><a class="reference external" href="http://goo.gl/W759t">Using Coroutines to Create Efficient, High-Concurrency Web
Applications</a> 介绍Python协程的。</li>
<li><a class="reference external" href="http://goo.gl/95PtV">Advanced Network Architectures With ZeroMQ</a></li>
<li>待补充...,欢迎大家推荐Pycon2011视频源。</li>
</ul>
如何在开发测试和生产环境下跑同一套Python代码2011-03-14T13:27:00+08:002011-03-14T13:27:00+08:00飞龙tag:feilong.me,2011-03-14:/2011/03/run-some-code-in-testing-and-deploying-server.html<p>通常在开发测试和生产环境下,程序的配置和系统环境等会有所差异,比如最常见的调试DEBUG选项本地一般是开的,而在生产环境这个肯定是要关闭的。手动维护两套配置显然是不明智的,下面介绍一点小技巧,让你可以轻松实现一套代码同时跑在开发测试和生产环境下。</p>
<p>下面以Django为例(Tornado、Pylons等类似)</p>
<p>首先需要判断当前环境是开发环境还是生产环境,常见的方式是检测机器名。</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">platform</span>
<span class="k">if</span> <span class="n">platform</span><span class="o">.</span><span class="n">node</span><span class="p">()</span> <span class="o">==</span> <span class="s2">"FELINX"</span><span class="p">:</span> <span class="c1"># FELINX is the name of felinx' EC2 server.</span>
<span class="n">DEBUG</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">DEBUG</span> <span class="o">=</span> <span class="bp">True</span>
</pre></div>
<p>不清楚机器名的话,可以通过hostname命令来查询和修改,下面是修改的命令。</p>
<div class="highlight"><pre><span></span><span class="n">sudo</span> <span class="n">hostname</span> <span class="n">xxx</span>
</pre></div>
<p>这样在开发环境和生产环境的DEBUG选项就不一样了,接下来对有需要区别对待的配置或代码就可以通过检测DEBUG来进行选择了,比如在<a class="reference external" href="http://www.chinapy.org">http://www.chinapy.org</a>的<a class="reference external" href="https://bitbucket.org/felinx/chinapy/src/tip/chinapy/settings_local.py">settings_local.py</a>中有这么一段代码:</p>
<div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">DEBUG …</span></pre></div><p>通常在开发测试和生产环境下,程序的配置和系统环境等会有所差异,比如最常见的调试DEBUG选项本地一般是开的,而在生产环境这个肯定是要关闭的。手动维护两套配置显然是不明智的,下面介绍一点小技巧,让你可以轻松实现一套代码同时跑在开发测试和生产环境下。</p>
<p>下面以Django为例(Tornado、Pylons等类似)</p>
<p>首先需要判断当前环境是开发环境还是生产环境,常见的方式是检测机器名。</p>
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">platform</span>
<span class="k">if</span> <span class="n">platform</span><span class="o">.</span><span class="n">node</span><span class="p">()</span> <span class="o">==</span> <span class="s2">"FELINX"</span><span class="p">:</span> <span class="c1"># FELINX is the name of felinx' EC2 server.</span>
<span class="n">DEBUG</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">DEBUG</span> <span class="o">=</span> <span class="bp">True</span>
</pre></div>
<p>不清楚机器名的话,可以通过hostname命令来查询和修改,下面是修改的命令。</p>
<div class="highlight"><pre><span></span><span class="n">sudo</span> <span class="n">hostname</span> <span class="n">xxx</span>
</pre></div>
<p>这样在开发环境和生产环境的DEBUG选项就不一样了,接下来对有需要区别对待的配置或代码就可以通过检测DEBUG来进行选择了,比如在<a class="reference external" href="http://www.chinapy.org">http://www.chinapy.org</a>的<a class="reference external" href="https://bitbucket.org/felinx/chinapy/src/tip/chinapy/settings_local.py">settings_local.py</a>中有这么一段代码:</p>
<div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">DEBUG</span><span class="p">:</span>
<span class="n">CACHE_BACKEND</span> <span class="o">=</span> <span class="s1">'file://</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s1">'cache'</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'</span><span class="se">\\</span><span class="s1">'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">)</span>
<span class="n">SESSION_ENGINE</span> <span class="o">=</span> <span class="s1">'django.contrib.sessions.backends.db'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">CACHE_BACKEND</span> <span class="o">=</span> <span class="s1">'memcached://127.0.0.1:11211'</span>
<span class="n">SESSION_ENGINE</span> <span class="o">=</span> <span class="s1">'django.contrib.sessions.backends.cache'</span>
</pre></div>
<p>上面就实现了自动选择相应的CACHE和SESSION配置,这样相同的代码就可以跑在开发环境和生产环境了。</p>
囧,Amazon AWS EC2硬件故障2011-03-06T12:44:00+08:002011-03-06T12:44:00+08:00飞龙tag:feilong.me,2011-03-06:/2011/03/amazon-aws-ec2-hardware-failure.html<p>今天早上起来开Gmail又收到一封来自Amazon的邮件,这次不是新功能的Annoucement邮件也不是Billing邮件,而是一封Notice邮件,惊了我一声冷汗,邮件内容如下(部分内容打了马赛克):</p>
<pre class="literal-block">
Hello,
We have noticed that one or more of your instances are running on a host degraded due to hardware failure.
i-221bdxxx
The risk of your instances failing is increased at this point. We cannot determine the health of any applications running on the …</pre><p>今天早上起来开Gmail又收到一封来自Amazon的邮件,这次不是新功能的Annoucement邮件也不是Billing邮件,而是一封Notice邮件,惊了我一声冷汗,邮件内容如下(部分内容打了马赛克):</p>
<pre class="literal-block">
Hello,
We have noticed that one or more of your instances are running on a host degraded due to hardware failure.
i-221bdxxx
The risk of your instances failing is increased at this point. We cannot determine the health of any applications running on the instances. We recommend that you launch replacement instances and start migrating to them.
Feel free to terminate the instances with the ec2-terminate-instance API when you are done with them.
Sincerely,
The Amazon EC2 Team
Reference: d3941eb8-xxxx-4caa-abc8-db9ae774xxxx
</pre>
<p>果然,访问我的博客出现502 Bad
Gateway错误,只有nginx还工作正常,我的EC2中的MySQL、mongodb和代码等全部部署在mount进来的一个ebs
volume上,而这个ebs volume居然硬件故障挂了,赶紧进行修复,修复过程如下:</p>
<ol class="arabic simple">
<li>新建一个ebs volume(主要是顺便扩大一下容量,准备给
<a class="reference external" href="http://www.chinapy.org/">http://www.chinapy.org</a> 留空间)</li>
<li>Attach进来一个备份的snapshot,然后连文件带属性把所有的文件拷贝到新的ebs
volume里(跟旧的保持一模一样的文件路径和属性)</li>
<li>mongodb因为是异常中断的,需要跑--repair修复一下</li>
<li>再重启一下所有相关的进程如MySQL、Python、Fast-CGI进程等</li>
<li>OK,一切恢复如初。</li>
</ol>
<p>如果不是要新建一个ebs
volume的话,只需要Attach进备份的snapshot,再过一下步骤3、4就OK了。</p>
<p>PS:
做好备份很重要,虽然EC2出硬件故障这事很少见,但做好备份是必须的,有备份的snapshot,在AWS上恢复数据是件非常简单的事情。</p>
用monit监控系统关键进程2011-02-24T17:36:00+08:002011-02-24T17:36:00+08:00飞龙tag:feilong.me,2011-02-24:/2011/02/monitor-core-processes-with-monit.html<p><a class="reference external" href="http://mmonit.com/monit/">monit</a>是一款功能强大的系统状态、进程、文件、目录和设备的监控软件,用于*nix平台,
它可以自动重启那些已经挂掉的程序,非常适合监控系统关键的进程和资源,如:nginx、apache、mysql和cpu占有率等。而监控管理Python进程,常用的是<a class="reference external" href="http://supervisord.org/">supervisor</a>,后续会另外撰文介绍。</p>
<p>下面分别介绍monit的安装、配置和启动。</p>
<div class="section" id="id1">
<h2>安装</h2>
<p>在debian或ubuntu上安装monit非常方便,通过下面的命令</p>
<pre class="literal-block">
sudo apt-get install monit
</pre>
<p>即可,其它*nix上也很简单,下载源码走一遍安装三步就OK了。</p>
<pre class="literal-block">
./configure
make
make install
</pre>
<p>安装后,默认的配置文件为/etc/monit/monitrc。</p>
</div>
<div class="section" id="id2">
<h2>配置</h2>
<p>添加需要监控的进程等信息至monit的配置文件,monit的配置详见下面的示例文件,为了便于理解,关键的配置我都给出了中文的注释。</p>
<pre class="literal-block">
##
## 飞龙札记 示例monit配置文件,说明:
## 1. 域名以example.com为例 …</pre></div><p><a class="reference external" href="http://mmonit.com/monit/">monit</a>是一款功能强大的系统状态、进程、文件、目录和设备的监控软件,用于*nix平台,
它可以自动重启那些已经挂掉的程序,非常适合监控系统关键的进程和资源,如:nginx、apache、mysql和cpu占有率等。而监控管理Python进程,常用的是<a class="reference external" href="http://supervisord.org/">supervisor</a>,后续会另外撰文介绍。</p>
<p>下面分别介绍monit的安装、配置和启动。</p>
<div class="section" id="id1">
<h2>安装</h2>
<p>在debian或ubuntu上安装monit非常方便,通过下面的命令</p>
<pre class="literal-block">
sudo apt-get install monit
</pre>
<p>即可,其它*nix上也很简单,下载源码走一遍安装三步就OK了。</p>
<pre class="literal-block">
./configure
make
make install
</pre>
<p>安装后,默认的配置文件为/etc/monit/monitrc。</p>
</div>
<div class="section" id="id2">
<h2>配置</h2>
<p>添加需要监控的进程等信息至monit的配置文件,monit的配置详见下面的示例文件,为了便于理解,关键的配置我都给出了中文的注释。</p>
<pre class="literal-block">
##
## 飞龙札记 示例monit配置文件,说明:
## 1. 域名以example.com为例。
## 2. 后面带xxx的均是举例用的名字,需要根据自己的需要修改。
##
###############################################################################
## Monit control file
###############################################################################
#
# 检查周期,默认为2分钟,对于网站来说有点长,可以根据需要自行调节,这改成30秒。
set daemon 30
# 日志文件
set logfile /var/log/monit.log
#
# 邮件通知服务器
#
#set mailserver mail.example.com
set mailserver localhost
#
# 通知邮件的格式设置,下面是默认格式供参考
#
## Monit by default uses the following alert mail format:
##
## --8<--
## From: monit@$HOST # sender
## Subject: monit alert -- $EVENT $SERVICE # subject
##
## $EVENT Service $SERVICE #
## #
## Date: $DATE #
## Action: $ACTION #
## Host: $HOST # body
## Description: $DESCRIPTION #
## #
## Your faithful employee, #
## monit #
## --8<--
##
## You can override the alert message format or its parts such as subject
## or sender using the MAIL-FORMAT statement. Macros such as $DATE, etc.
## are expanded on runtime. For example to override the sender:
#
# 简单的,这只改了一下发送人,有需要可以自己修改其它内容。
set mail-format { from: webmaster@example.com }
# 设置邮件通知接收者。建议发到gmail,方便邮件过滤。
set alert userxxx@gmail.com
set httpd port 2812 and # 设置http监控页面的端口
use address www.example.com # http监控页面的IP或域名
allow localhost # 允许本地访问
allow 58.68.78.0/24 # 允许此IP段访问
##allow 0.0.0.0/0.0.0.0 # 允许任何IP段,不建议这样干
allow userxxx:passwordxxx # 访问用户名密码
###############################################################################
## Services
###############################################################################
#
# 系统整体运行状况监控,默认的就可以,可以自己去微调
#
# 系统名称,可以是IP或域名
check system www.example.com
if loadavg (1min) > 4 then alert
if loadavg (5min) > 2 then alert
if memory usage > 75% then alert
if cpu usage (user) > 70% then alert
if cpu usage (system) > 30% then alert
if cpu usage (wait) > 20% then alert
#
# 监控nginx
#
# 需要提供进程pid文件信息
check process nginx with pidfile /var/run/nginx.pid
# 进程启动命令行,注:必须是命令全路径
start program = "/etc/init.d/nginx start"
# 进程关闭命令行
stop program = "/etc/init.d/nginx stop"
# nginx进程状态测试,监测到nginx连不上了,则自动重启
if failed host www.example.com port 80 protocol http then restart
# 多次重启失败将不再尝试重启,这种就是系统出现严重错误的情况
if 3 restarts within 5 cycles then timeout
# 可选,设置分组信息
group server
# 可选的ssl端口的监控,如果有的话
# if failed port 443 type tcpssl protocol http
# with timeout 15 seconds
# then restart
#
# 监控apache
#
check process apache with pidfile /var/run/apache2.pid
start program = "/etc/init.d/apache2 start"
stop program = "/etc/init.d/apache2 stop"
# apache吃cpu和内存比较厉害,额外添加一些关于这方面的监控设置
if cpu > 50% for 2 cycles then alert
if cpu > 70% for 5 cycles then restart
if totalmem > 1500 MB for 10 cycles then restart
if children > 250 then restart
if loadavg(5min) greater than 10 for 20 cycles then stop
if failed host www.example.com port 8080 protocol http then restart
if 3 restarts within 5 cycles then timeout
group server
# 可选,依赖于nginx
depends on nginx
#
# 监控spawn-fcgi进程(其实就是fast-cgi进程)
#
check process spawn-fcgi with pidfile /var/run/spawn-fcgi.pid
# spawn-fcgi一定要带-P参数才会生成pid文件,默认是没有的
start program = "/usr/bin/spawn-fcgi -a 127.0.0.1 -p 8081 -C 10 -u userxxx -g groupxxx -P /var/run/spawn-fcgi.pid -f /usr/bin/php-cgi"
stop program = "/usr/bin/killall /usr/bin/php-cgi"
# fast-cgi走的不是http协议,monit的protocol参数也没有cgi对应的设置,这里去掉protocol http即可。
if failed host 127.0.0.1 port 8081 then restart
if 3 restarts within 5 cycles then timeout
group server
depends on nginx
</pre>
<p>虽然在注释里有详细说明,但是我还是要再强调说明几点:</p>
<ol class="arabic simple">
<li>start和stop的program参数里的命令必须是全路径,否则monit不能正常启动,比如killall应该是/usr/bin/killall。</li>
<li>对于spawn-fcgi,很多人会用它来管理PHP的fast-cgi进程,但spawn-fcgi本身也是有可能挂掉的,所以还是需要用monit来监控spawn-fcgi。spawn-fcgi必须带-P参数才会有pid文件,而且fast-cgi走的不是http协议,monit的protocol参数也没有cgi对应的设置,一定要去掉protocol
http这项设置才管用。</li>
<li>进程多次重启失败monit将不再尝试重启,收到这样的通知邮件表明系统出现了严重的问题,要引起足够的重视,需要赶紧人工处理。</li>
</ol>
<p>当然monit除了管理进程之外,还可以监控文件、目录、设备等,本文不做讨论,具体配置方式可以去参考<a class="reference external" href="http://mmonit.com/monit/documentation/monit.html">monit的官方文档</a>。</p>
</div>
<div class="section" id="id3">
<h2>启动、停止、重启</h2>
<p>标准的start、stop、restart</p>
<pre class="literal-block">
sudo /etc/init.d/monit start
sudo /etc/init.d/monit stop
sudo /etc/init.d/monit restart
</pre>
<p>看到正确的提示信息即可,若遇到问题可以去查看配置里指定的日志文件,如/var/log/monit.log。</p>
<p>从我的服务器这几年的运行情况(monit发了的通知邮件)来看,nginx挂掉的事几乎没有,但apache或fast-cgi出问题的情况还是比较多见,赶快用上monit来管理你的服务器以提高服务器稳定性,跟502
Bad Gateway之类错误说拜拜吧。</p>
<p>附件:<a class="reference external" href="/static/2011/02/monitrc.txt">monit示例配置文件</a>
(注:下载后请去掉.txt文件后缀)</p>
</div>
Python兼容性编程2011-02-21T18:17:00+08:002011-02-21T18:17:00+08:00飞龙tag:feilong.me,2011-02-21:/2011/02/learning-python-follow-felinx-part-one.html<p>鉴于我前面的博客里,Python相关的文章最受欢迎,我决定再接再厉,多写一些跟Python相关的文章,把我琢磨Python的一点经验拿出来分享,算是抛个砖,欢迎大家<strong>讨论、拍砖、献花</strong>!</p>
<p>我将主要结合<a class="reference external" href="http://github.com/facebook/tornado">Tornado的源码</a>来讲解一些Python的编程技巧和相对较高级一点的Python知识,这样大家就可以看到活生生的实际运用而不是枯燥的理论。</p>
<p>为什么选择拿Tornado的源码来讲而不是其它的Python项目呢,主要是因为:</p>
<ol class="arabic simple">
<li>Tornado的代码规范且质量很高;</li>
<li>代码总量比较小,比较容易掌握;</li>
<li>飞龙对Tornado多多少少有点研究。</li>
</ol>
<p>注:<a class="reference external" href="http://www.tornadoweb.org/">Tornado(要翻墙)</a>是<a class="reference external" href="http://friendfeed.com">friendfeed.com</a>(已并入facebook)开源出来的一个高性能的异步非阻塞模式的Web
server,同时又是一个类web.py的web框架,关于Tornado
web框架部分的讨论见我的博客“ <a class="reference external" href="http://feilong.me/2011/01/talk-about-python-web-framework">浅谈Python
web框架</a>”相应的部分,对于Tornado的web
server的性能,可以参考Tornado官方主页和<a class="reference external" href="http://nichol.as/benchmark-of-python-web-servers">http://nichol.as/benchmark-of-python-web-servers</a>的介绍。</p>
<p>看了本篇标题,有些朋友可能会很好奇,啥不好讲为什么先讲兼容性这个话题?原因其实很简单,因为这部分的代码经常出现在Python文件的开头:)</p>
<div class="section" id="id1">
<h2>系统兼容 …</h2></div><p>鉴于我前面的博客里,Python相关的文章最受欢迎,我决定再接再厉,多写一些跟Python相关的文章,把我琢磨Python的一点经验拿出来分享,算是抛个砖,欢迎大家<strong>讨论、拍砖、献花</strong>!</p>
<p>我将主要结合<a class="reference external" href="http://github.com/facebook/tornado">Tornado的源码</a>来讲解一些Python的编程技巧和相对较高级一点的Python知识,这样大家就可以看到活生生的实际运用而不是枯燥的理论。</p>
<p>为什么选择拿Tornado的源码来讲而不是其它的Python项目呢,主要是因为:</p>
<ol class="arabic simple">
<li>Tornado的代码规范且质量很高;</li>
<li>代码总量比较小,比较容易掌握;</li>
<li>飞龙对Tornado多多少少有点研究。</li>
</ol>
<p>注:<a class="reference external" href="http://www.tornadoweb.org/">Tornado(要翻墙)</a>是<a class="reference external" href="http://friendfeed.com">friendfeed.com</a>(已并入facebook)开源出来的一个高性能的异步非阻塞模式的Web
server,同时又是一个类web.py的web框架,关于Tornado
web框架部分的讨论见我的博客“ <a class="reference external" href="http://feilong.me/2011/01/talk-about-python-web-framework">浅谈Python
web框架</a>”相应的部分,对于Tornado的web
server的性能,可以参考Tornado官方主页和<a class="reference external" href="http://nichol.as/benchmark-of-python-web-servers">http://nichol.as/benchmark-of-python-web-servers</a>的介绍。</p>
<p>看了本篇标题,有些朋友可能会很好奇,啥不好讲为什么先讲兼容性这个话题?原因其实很简单,因为这部分的代码经常出现在Python文件的开头:)</p>
<div class="section" id="id1">
<h2>系统兼容</h2>
<p>Python和许多具有虚拟机的语言一样,支持跨平台,基本可以一次编写到处运行,所以大部分时候大家不用考虑系统兼容性的问题,跟系统相关的能用Python现成的API的就用,不要自己去蛮干就行。比如文件路径的拼接,你别自己傻乎乎的去做字符串拼接,而是用已封装好的os.path.join来实现。</p>
<p>如果你要实现的功能跟系统强相关或在不同的系统中实现是完全不一样的,那就需要考虑这个问题了,这个时候一般是把相关的API封装成一致,然后根据系统信息来选择不同的实现模块,Tornado示例代码如下(模块和代码行数见第一行注释,注:代码行可能会随着Tornado的升级而稍有变化,后面不再做特别说明):</p>
<div class="highlight"><pre><span></span><span class="c1"># tornado.httpserver line 32</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">fcntl</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s1">'nt'</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">tornado</span> <span class="kn">import</span> <span class="n">win32_support</span> <span class="k">as</span> <span class="n">fcntl</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span>
</pre></div>
<p>在windows上运行和在linux下运行,导入的fcntl模块是不同的,windows下导入的是Tornado的win32_support这个实验性质的模块,当然API接口做的跟fcntl是一致的,而在具体用到fcntl的部分就不再需要考虑系统兼容性的问题了,更复杂一点的一个例子见:</p>
<div class="highlight"><pre><span></span><span class="c1"># tornado.ioloop line 539</span>
<span class="c1"># Choose a poll implementation. Use epoll if it is available, fall back to</span>
<span class="c1"># select() for non-Linux platforms</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">select</span><span class="p">,</span> <span class="s2">"epoll"</span><span class="p">):</span>
<span class="c1"># Python 2.6+ on Linux</span>
<span class="n">_poll</span> <span class="o">=</span> <span class="n">select</span><span class="o">.</span><span class="n">epoll</span>
<span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">select</span><span class="p">,</span> <span class="s2">"kqueue"</span><span class="p">):</span>
<span class="c1"># Python 2.6+ on BSD or Mac</span>
<span class="n">_poll</span> <span class="o">=</span> <span class="n">_KQueue</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Linux systems with our C module installed</span>
<span class="kn">import</span> <span class="nn">epoll</span>
<span class="n">_poll</span> <span class="o">=</span> <span class="n">_EPoll</span>
<span class="k">except</span><span class="p">:</span>
<span class="c1"># All other systems</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">if</span> <span class="s2">"linux"</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span><span class="p">:</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s2">"epoll module not found; using select()"</span><span class="p">)</span>
<span class="n">_poll</span> <span class="o">=</span> <span class="n">_Select</span>
</pre></div>
<p>其实就是在不同的操作系统上选择不同的poll实现,至于模块在不同操作系统是如何实现那是另一个问题了。</p>
<p>通过这种方式可以有效的屏蔽不同系统下的编程差异,降低系统兼容性编程的复杂度。</p>
</div>
<div class="section" id="id2">
<h2>向下兼容</h2>
<p>软件版本都避免不了升级,版本一多就有了版本向下兼容的问题(特别的,Python3.x是不向下兼容Python2.x的),这个时候代码里就需要一些向下兼容的代码,主要表现有两种,下面分别介绍:</p>
<div class="section" id="id3">
<h3>兼容不同的Python版本</h3>
<p>这类最常见的就是用try、import、except三者组成的黄金搭档,Tornado代码举例如下:</p>
<div class="highlight"><pre><span></span><span class="c1"># tornado.escape line 24</span>
<span class="c1"># json module is in the standard library as of python 2.6; fall back to</span>
<span class="c1"># simplejson if present for older versions.</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="k">assert</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">json</span><span class="p">,</span> <span class="s2">"loads"</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">json</span><span class="p">,</span> <span class="s2">"dumps"</span><span class="p">)</span>
<span class="n">_json_decode</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span>
<span class="n">_json_encode</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">simplejson</span>
<span class="n">_json_decode</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">simplejson</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">_unicode</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>
<span class="n">_json_encode</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="n">simplejson</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># For Google AppEngine</span>
<span class="kn">from</span> <span class="nn">django.utils</span> <span class="kn">import</span> <span class="n">simplejson</span>
<span class="n">_json_decode</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">simplejson</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">_unicode</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>
<span class="n">_json_encode</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="n">simplejson</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">_json_decode</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span>
<span class="s2">"A JSON parser is required, e.g., simplejson at "</span>
<span class="s2">"http://pypi.python.org/pypi/simplejson/"</span><span class="p">)</span>
<span class="n">_json_encode</span> <span class="o">=</span> <span class="n">_json_decode</span>
</pre></div>
<p>这段这么长的代码的目的其实只有一个,就是导入可用的json模块,分别尝试用Python2.6+自带的json模块、simplejson第三方包、django环境里的simplejson(其实和前面的simplejson是一个东西,不过django把它集成到它自己的utils里去了),若都缺的话最后会抛一个常用来表功能未实现的异常(NotImplementedError)。有了这段代码,在Python2.6+、Python2.5+simplejson、Python2.5+django的Python环境下,Tornado的json编解码的功能都能够正常使用。
更常见一点的例子,如:</p>
<div class="highlight"><pre><span></span><span class="c1"># tornado.httpserver line 40</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">ssl</span> <span class="c1"># Python 2.6+</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="n">ssl</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">multiprocessing</span> <span class="c1"># Python 2.6+</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="n">multiprocessing</span> <span class="o">=</span> <span class="bp">None</span>
</pre></div>
<p>然后后面一般会有针对性的处理,如:</p>
<div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">multiprocessing</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="c1"># do something</span>
</pre></div>
</div>
<div class="section" id="api">
<h3>兼容API的变化</h3>
<p>无论事先有多好的设计,API的变化多多少少总是不可避免的,API的变化必然会带来软件兼容性的问题,在Python的世界里,因为Python特殊的变量机制(如下图,详见:<a class="reference external" href="../2011/01/recommended-entries-for-you-to-master-python">学好Python必读的几篇文章</a>
里推荐的第二篇文章 <a class="reference external" href="http://python.net/%7Egoodger/projects/pycon/2007/idiomatic/handout.html">Code Like a Pythonista: Idiomatic
Python</a>),</p>
<p><img alt="image0" src="/static/2011/02/ab2tag.jpg" style="width: 153px; height: 88px;" /></p>
<p>这个问题通常变得异常的简单,Tornado示例如下:</p>
<div class="highlight"><pre><span></span><span class="c1"># tornado.httpclient line 367</span>
<span class="c1"># For backwards compatibility: Tornado 1.0 included a new implementation of</span>
<span class="c1"># AsyncHTTPClient that has since replaced the original. Define an alias</span>
<span class="c1"># so anything that used AsyncHTTPClient2 still works</span>
<span class="n">AsyncHTTPClient2</span> <span class="o">=</span> <span class="n">AsyncHTTPClient</span>
</pre></div>
<p>你没有看错,除了注释,代码其实就那么一行。
Tornado最早的版本就有一个AsyncHTTPClient实现,但是在中间又引人了一个实验性质的AsyncHTTPClient把它命名为AsyncHTTPClient2以示区别,AsyncHTTPClient2比AsyncHTTPClient更强劲,后来功能稳定了Tornado就把AsyncHTTPClient2的代码移到了AsyncHTTPClient中当作默认的实现。</p>
<p>接下来问题就来了,如果直接把AsyncHTTPClient2的代码都去掉,还在用AsyncHTTPClient2的同学一旦升级了Tornado就糟了,而如果继续保持AsyncHTTPClient2的全部代码不动,那就会有两份几乎一模一样的冗余代码,优雅的解决这个问题实际上只需要上面这么一行代码,AsyncHTTPClient2的代码可以全部撤下,因为这样无论用户在用AsyncHTTPClient还是AsyncHTTPClient2,实际用的会是同一个API。</p>
<p>这一解决方案非常实用的,许多地方都可以看到它的影子,再给大家举个例子,旧的多线程模块threading的实现其命名规范是不符合现在的PEP8标准的,而它提供符合PEP8标准的API的方式也很简单,示例代码片段如下:</p>
<div class="highlight"><pre><span></span><span class="c1"># python2.6 threading line 799</span>
<span class="c1"># Global API functions</span>
<span class="k">def</span> <span class="nf">currentThread</span><span class="p">():</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">_active</span><span class="p">[</span><span class="n">_get_ident</span><span class="p">()]</span>
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
<span class="c1">##print "current_thread(): no current thread for", _get_ident()</span>
<span class="k">return</span> <span class="n">_DummyThread</span><span class="p">()</span>
<span class="n">current_thread</span> <span class="o">=</span> <span class="n">currentThread</span>
<span class="k">def</span> <span class="nf">activeCount</span><span class="p">():</span>
<span class="n">_active_limbo_lock</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
<span class="n">count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">_active</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">_limbo</span><span class="p">)</span>
<span class="n">_active_limbo_lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
<span class="k">return</span> <span class="n">count</span>
<span class="n">active_count</span> <span class="o">=</span> <span class="n">activeCount</span>
</pre></div>
</div>
</div>
<div class="section" id="id4">
<h2>向上兼容</h2>
<p>向上兼容这个可能少有人听过,但在Python这奇妙的世界里,还真有这事,这就是神秘的__future__模块,你可能看到过下面这样的代码:</p>
<div class="highlight"><pre><span></span><span class="c1"># tornado.httpclient line 19</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</pre></div>
<p>这就是在消费Python未来的成果(将来或说较新的版本才有的特性),在较低的版本里就可以使用较高版本里才会正式成为Python一部分的新特性,这里是后面的代码有用到with表达式(关于它将来会另外写博客介绍),深入进__future__模块的代码,里面有这么几行:</p>
<div class="highlight"><pre><span></span><span class="n">with_statement</span> <span class="o">=</span> <span class="n">_Feature</span><span class="p">((</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"alpha"</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span>
<span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"alpha"</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
<span class="n">CO_FUTURE_WITH_STATEMENT</span><span class="p">)</span>
</pre></div>
<p>前两行tuple分别表示首次引入的版本和预测的即将成为Python正式的一部分的版本信息,针对with表达式,这里的意思就是说with是在Python2.5的版本才实验性引入的,但需要用前面那句import才能够正常使用,而在Python2.6中可能会(实事已经)成为正式Python的一部分,即可以不用import那句就可以直接用了。
__future__里引入的特性都将成为未来版本里实事上的标准,但是在一些实验性引入该特性的低版本里通过__future__也可以用,将来升级了Python版本,用了新特性的代码也不会有兼容性的问题了。</p>
<p>总之,Python很容易写出兼容性很好的程序,可是杯具的是Python3.x不完全兼容2.x,导致Python3.x推出来这么久了迟迟没有得到大规模的运用。</p>
</div>
教你一招,让你快速找到自己最早的Buzz2011-02-10T11:32:00+08:002011-02-10T11:32:00+08:00飞龙tag:feilong.me,2011-02-10:/2011/02/quick-find-your-oldest-buzz.html<p>Google
Buzz推出已有一周年,最近很多网友想怀怀旧,把自己的处女Buzz给找出来记念一下,可是很不幸Google
Buzz要做到这一点还真不容易,在个人的Buzz页面你只能一步步Load老的Buzz,没有翻到最后一页之说,如下图:</p>
<p><img alt="image0" class="alignnone size-full wp-image-235" src="/static/2011/02/buzz_load_more.jpg" style="width: 436px; height: 186px;" /></p>
<p>如果你的Buzz很多的话,对不起,Load旧的Buzz到一定程度就进行不下去了,没法Load到最后一页去挖最早的一篇Buzz。</p>
<p>难道要找自己最早的Buzz就这么难吗?办法是有地,接下来就教你一招搞定这事。</p>
<p>我们可以通过Gmail的邮件搜索来找到你最早的Buzz,在Gmail里搜索关键字“buzz”:</p>
<p><img alt="image1" class="alignnone size-full wp-image-236" src="/static/2011/02/search_buzz_in_gmail.jpg" style="width: 538px; height: 62px;" /></p>
<p>搜索结果包括你发的所有健在的Buzz记录,结果如下:</p>
<p><img alt="image2" class="alignnone size-large wp-image-237" src="/static/2011/02/search_buzz_result-1024x103.jpg" style="width: 725px; height: 72px;" /></p>
<p>接下来就是点右上角或左下角的Older链接不停的翻旧的Buzz就可以了,翻到最后一页就是你最早的Buzz记录了(这个是可以一直翻到底的哦)。</p>
<p>我就是这样把最早的一条Buzz给翻出来的,你还不赶紧按此法把自己的处女Buzz挖出来顶顶。</p>
<p>Google
Buzz推出已有一周年,最近很多网友想怀怀旧,把自己的处女Buzz给找出来记念一下,可是很不幸Google
Buzz要做到这一点还真不容易,在个人的Buzz页面你只能一步步Load老的Buzz,没有翻到最后一页之说,如下图:</p>
<p><img alt="image0" class="alignnone size-full wp-image-235" src="/static/2011/02/buzz_load_more.jpg" style="width: 436px; height: 186px;" /></p>
<p>如果你的Buzz很多的话,对不起,Load旧的Buzz到一定程度就进行不下去了,没法Load到最后一页去挖最早的一篇Buzz。</p>
<p>难道要找自己最早的Buzz就这么难吗?办法是有地,接下来就教你一招搞定这事。</p>
<p>我们可以通过Gmail的邮件搜索来找到你最早的Buzz,在Gmail里搜索关键字“buzz”:</p>
<p><img alt="image1" class="alignnone size-full wp-image-236" src="/static/2011/02/search_buzz_in_gmail.jpg" style="width: 538px; height: 62px;" /></p>
<p>搜索结果包括你发的所有健在的Buzz记录,结果如下:</p>
<p><img alt="image2" class="alignnone size-large wp-image-237" src="/static/2011/02/search_buzz_result-1024x103.jpg" style="width: 725px; height: 72px;" /></p>
<p>接下来就是点右上角或左下角的Older链接不停的翻旧的Buzz就可以了,翻到最后一页就是你最早的Buzz记录了(这个是可以一直翻到底的哦)。</p>
<p>我就是这样把最早的一条Buzz给翻出来的,你还不赶紧按此法把自己的处女Buzz挖出来顶顶。</p>
浅谈Python web框架2011-01-25T19:01:00+08:002011-01-25T19:01:00+08:00飞龙tag:feilong.me,2011-01-25:/2011/01/talk-about-python-web-framework.html<p>说到web
framework,Ruby的世界Rails一统江湖,而Python则是一个百花齐放的世界,各种micro-framework、framework不可胜数,不完全列表见:<a class="reference external" href="http://wiki.python.org/moin/WebFrameworks">http://wiki.python.org/moin/WebFrameworks</a>。虽然另一大脚本语言PHP也有不少框架,但远没有Python这么夸张,也正是因为Python
web framework(Python
web开发框架,以下简称Python框架)太多,所以在Python社区总有关于Python框架孰优孰劣的话题,讨论的时间跨度甚至长达3-5年。</p>
<p>Python这么多框架,能挨个玩个遍的人不多,坦白的说我也只用过其中的三个开发过项目,另外一些稍微接触过,所以这里只能浅谈一下,欢迎懂行的朋友们补充、拍砖。</p>
<div class="section" id="django">
<h2><a class="reference external" href="http://www.djangoproject.com">Django</a></h2>
</div>
<div class="section" id="image0">
<h2><img alt="image0" class="alignnone size-full wp-image-225" src="/static/2011/01/hdr_logo.gif" style="width: 117px; height: 41px;" /></h2>
<p>Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django。要说Django是Python框架里最好的,有人同意也有人坚决反对,但说Django的文档最完善、市场占有率最高、招聘职位最多估计大家都没什么意见。Django为人所称道的地方主要有:</p>
<ul class="simple">
<li>完美的文档,Django的成功,我觉得很大一部分原因要归功于Django近乎完美的官方文档(包括Django
book)。</li>
<li>全套的解决方案,Django象Rails一样,提供全套的解决方案(full-stack …</li></ul></div><p>说到web
framework,Ruby的世界Rails一统江湖,而Python则是一个百花齐放的世界,各种micro-framework、framework不可胜数,不完全列表见:<a class="reference external" href="http://wiki.python.org/moin/WebFrameworks">http://wiki.python.org/moin/WebFrameworks</a>。虽然另一大脚本语言PHP也有不少框架,但远没有Python这么夸张,也正是因为Python
web framework(Python
web开发框架,以下简称Python框架)太多,所以在Python社区总有关于Python框架孰优孰劣的话题,讨论的时间跨度甚至长达3-5年。</p>
<p>Python这么多框架,能挨个玩个遍的人不多,坦白的说我也只用过其中的三个开发过项目,另外一些稍微接触过,所以这里只能浅谈一下,欢迎懂行的朋友们补充、拍砖。</p>
<div class="section" id="django">
<h2><a class="reference external" href="http://www.djangoproject.com">Django</a></h2>
</div>
<div class="section" id="image0">
<h2><img alt="image0" class="alignnone size-full wp-image-225" src="/static/2011/01/hdr_logo.gif" style="width: 117px; height: 41px;" /></h2>
<p>Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django。要说Django是Python框架里最好的,有人同意也有人坚决反对,但说Django的文档最完善、市场占有率最高、招聘职位最多估计大家都没什么意见。Django为人所称道的地方主要有:</p>
<ul class="simple">
<li>完美的文档,Django的成功,我觉得很大一部分原因要归功于Django近乎完美的官方文档(包括Django
book)。</li>
<li>全套的解决方案,Django象Rails一样,提供全套的解决方案(full-stack
framework + batteries
included),基本要什么有什么(比如:cache、session、feed、orm、geo、auth),而且全部Django自己造,开发网站应手的工具Django基本都给你做好了,因此开发效率是不用说的,出了问题也算好找,不在你的代码里就在Django的源码里。</li>
<li>强大的URL路由配置,Django让你可以设计出非常优雅的URL,在Django里你基本可以跟丑陋的GET参数说拜拜。</li>
<li>自助管理后台,admin
interface是Django里比较吸引眼球的一项contrib,让你几乎不用写一行代码就拥有一个完整的后台管理界面。</li>
</ul>
<p>而Django的缺点主要源自Django坚持自己造所有的轮子,整个系统相对封闭,Django最为人诟病的地方有:</p>
<ul>
<li><p class="first">系统紧耦合,如果你觉得Django内置的某项功能不是很好,想用喜欢的第三方库来代替是很难的,比如下面将要说的ORM、Template。要在Django里用SQLAlchemy或Mako几乎是不可能,即使打了一些补丁用上了也会让你觉得非常非常别扭。</p>
</li>
<li><p class="first">Django自带的ORM远不如SQLAlchemy强大,除了在Django这一亩三分地,SQLAlchemy是Python世界里事实上的ORM标准,其它框架都支持SQLAlchemy了,唯独Django仍然坚持自己的那一套。Django的开发人员对SQLAlchemy的支持也是有过讨论和尝试的,不过最终还是放弃了,估计是代价太高且跟Django其它的模块很难合到一块。</p>
</li>
<li><p class="first">Template功能比较弱,不能插入Python代码,要写复杂一点的逻辑需要另外用Python实现Tag或Filter。关于模板这一点,一直以来争论比较多,最近有两篇关于Python模板的比较有意思的文章可供参考:</p>
<blockquote>
<ol class="arabic simple">
<li><a class="reference external" href="http://pydanny.blogspot.com/2010/12/stupid-template-languages.html">http://pydanny.blogspot.com/2010/12/stupid-template-languages.html</a>(需翻墙)</li>
<li><a class="reference external" href="http://techspot.zzzeek.org/2010/12/04/in-response-to-stupid-template-languages/">http://techspot.zzzeek.org/2010/12/04/in-response-to-stupid-template-languages/</a></li>
</ol>
</blockquote>
</li>
<li><p class="first">URL配置虽然强大,但全部要手写,这一点跟Rails的Convention over
configuration的理念完全相左,高手和初识Django的人配出来的URL会有很大差异。</p>
</li>
<li><p class="first">让人纠结的auth模块,Django的auth跟其它模块结合紧密,功能也挺强的,就是做的有点过了,用户的数据库schema都给你定好了,这样问题就来了,比如很多网站要求email地址唯一,可schema里这个字段的值不是唯一的,纠结是必须的了。</p>
</li>
<li><p class="first">Python文件做配置文件,而不是更常见的ini、xml或yaml等形式。这本身不是什么问题,可是因为理论上来说settings的值是能够动态的改变的(虽然大家不会这么干),但这不是最佳实践的体现。</p>
</li>
</ul>
<p>总的来说,Django大包大揽,用它来快速开发一些Web运用是很不错的。如果你顺着Django的设计哲学来,你会觉得Django很好用,越用越爽;相反,你如果不能融入或接受Django的设计哲学,你用Django一定会很痛苦,趁早放弃的好。所以说在有些人眼里Django无异于仙丹,但对有一些人来说它又是毒药且剧毒。</p>
<p>Django案例有<a class="reference external" href="http://disqus.com">disqus.com</a>、<a class="reference external" href="http://bitbucket.org">bitbucket.org</a>、<a class="reference external" href="http://www.haibao.cn">海报网</a>等。</p>
</div>
<div class="section" id="pylons-turbogears-repoze-bfg">
<h2><a class="reference external" href="http://www.pylonshq.com">Pylons</a> & <a class="reference external" href="http://turbogears.org/">TurboGears</a> & <a class="reference external" href="http://bfg.repoze.org/">repoze.bfg</a></h2>
<p><img alt="image1" class="alignnone size-full wp-image-226" src="/static/2011/01/pylons_logo.jpg" style="width: 346px; height: 102px;" /></p>
<p>除了Django另一个大头就是Pylons了,因为TurboGears2.x是基于Pylons来做的,而repoze.bfg也已经并入Pylons
project里这个大的项目里,后面不再单独讨论TurboGears和repoze.bfg了。</p>
<p>Pylons和Django的设计理念完全不同,Pylons本身只有两千行左右的Python代码,不过它还附带有一些几乎就是Pylons御用的第三方模块。Pylons只提供一个架子和可选方案,你可以根据自己的喜好自由的选择Template、ORM、form、auth等组件,系统高度可定制。我们常说Python是一个胶水语言(glue
language),那么我们完全可以说Pylons就是一个用胶水语言设计的胶水框架:)</p>
<p>选择Pylons多是选择了它的自由,选择了自由的同时也预示着你选择了噩梦:</p>
<ul class="simple">
<li>学习噩梦,Pylons依赖于许多第三方库,它们并不是Pylons造,你学Pylons的同时还得学这些库怎么使用,关键有些时候你都不知道你要学什么。Pylons的学习曲线相对比Django要高的多,而之前Pylons的官方文档也一直是人批评的对象,好在后来出了<a class="reference external" href="http://pylonsbook.com/en/1.1/">The
Definitive Guide to
Pylons</a>这本书,这一局面有所改观。因为这个原因,Pylons一度被誉为只适合高手使用的Python框架。</li>
<li>调试噩梦,因为牵涉到的模块多,一旦有错误发生就比较难定位问题处在哪里。可能是你写的程序的错、也可能是Pylons出错了、再或是SQLAlchemy出错了、搞不好是formencode有bug,反正很凌乱了。这个只有用的很熟了才能解决这个问题。</li>
<li>升级噩梦,安装Pylons大大小小共要安装近20个Python模块,各有各自的版本号,要升级Pylons的版本,哪个模块出了不兼容的问题都有可能,升级基本上很难很难。至今reddit的Pylons还停留在古董的0.9.6上,SQLAlchemy也还是0.5.3的版本,应该跟这条有关系。所以大家玩Pylons一定要结合virtualenv来玩,给自己留条后路,不然会死得很惨。</li>
</ul>
<p>Pylons和repoze.bfg的融合可能会催生下一个能挑战Django地位的框架。</p>
<p>Pylons的案例有<a class="reference external" href="http://www.reddit.com">reddit.com</a>、<a class="reference external" href="http://www.dropbox.com">dropbox.com</a>、<a class="reference external" href="http://www.quora.com">quora.com</a>等。</p>
</div>
<div class="section" id="tornado-web-py">
<h2><a class="reference external" href="http://www.tornadoweb.org">Tornado</a>& <a class="reference external" href="http://webpy.org/">web.py</a></h2>
<p><img alt="image2" class="alignnone size-full wp-image-227" src="/static/2011/01/tornado.png" style="width: 286px; height: 72px;" /></p>
<p>Tornado即是一个web
server(对此本文不作详述),同时又是一个类web.py的micro-framework,作为框架Tornado的思想主要来源于web.py,大家在web.py的网站首页也可以看到Tornado的大佬<a class="reference external" href="http://bret.appspot.com">Bret
Taylor</a>的这么一段话(他这里说的FriendFeed用的框架跟Tornado可以看作是一个东西):</p>
<blockquote>
"[web.py inspired the] web framework we use at FriendFeed [and] the
webapp framework that ships with App Engine..."</blockquote>
<p>因为有这层关系,后面不再单独讨论Tornado。</p>
<p>web.py的设计理念力求精简(Keep it simple and
powerful),总共就没多少行代码,也不像Pylons那样依赖大量的第三方模块,而是只提供的一个框架所必须的一些东西,如:URL路由、Template、数据库访问,其它的就交给用户自己去做好了。</p>
<div class="line-block">
<div class="line">一个框架精简的好处在于你可以聚焦在业务逻辑上,而不用太多的去关心框架本身或受框架的干扰,同时缺点也很明显,许多事情你得自己操刀上。</div>
<div class="line">我个人比较偏好这种精简的框架,因为你很容易通过阅读源码弄明白整个框架的工作机制,如果框架那一块不是很合意的话,我完全可以Monkey
patch一下按自己的要求来。</div>
</div>
<p>早期的reddit是用web.py写的,Tornado的案例有<a class="reference external" href="http://friendfeed.com">friendfeed.com</a>、<a class="reference external" href="http://bit.ly">bit.ly</a>、<a class="reference external" href="http://www.quora.com">quora.com</a>和我的开源站点<a class="reference external" href="http://poweredsites.org">poweredsites.org</a>等。</p>
</div>
<div class="section" id="bottle-flask">
<h2><a class="reference external" href="http://bottle.paws.de/">Bottle</a> & <a class="reference external" href="http://flask.pocoo.org/">Flask</a></h2>
<p><img alt="image3" class="alignnone size-full wp-image-228" src="/static/2011/01/bottle-logo.png" style="width: 276px; height: 100px;" /></p>
<p>Bottle和Flask作为新生一代Python框架的代表,挺有意思的是都采用了decorator的方式配置URL路由,如:</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span>
<span class="nd">@route</span><span class="p">(</span><span class="s1">'/:name'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'World'</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">'<b>Hello </span><span class="si">%s</span><span class="s1">!</b>'</span> <span class="o">%</span> <span class="n">name</span>
<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">)</span>
</pre></div>
<p>Bottle、Flask跟web.py一样,都非常精简,Bottle甚至所有的代码都在那一个两千来行的.py文件里。另外Flask和Pylons一样,可以跟Jinja2、SQLAlchemy之类结合的很好。</p>
<p>不过目前不管是Bottle还是Flask成功案例都还很少。</p>
</div>
<div class="section" id="quixote">
<h2><a class="reference external" href="http://www.quixote.ca/">Quixote</a></h2>
<p>之所以要特别说一下Quixote,是因为国内的最大的用Python开发的网站“<a class="reference external" href="http://www.douban.com">豆瓣网</a>”是用Quixote开发的。我只简单翻了一下源代码,没有做过研究,不发表评论,有经验的来补充下。我只是在想,如果豆瓣网交到现在来开发,应该会有更多的选择。</p>
</div>
<div class="section" id="web2pyuliwebkarrigellwerkzeug">
<h2>其它(web2py、uliweb、Karrigell、Werkzeug ...)</h2>
<p>欢迎大家补充...</p>
</div>
<div class="section" id="id1">
<h2>最后关于框架选择的误区</h2>
<p>在框架的选择问题上,许多人很容易就陷入了下面两个误区中而不自知:</p>
<ol class="arabic simple">
<li>哪个框架最好 -
世上没有最好的框架,只有最适合你自己、最适合你的团队的框架。编程语言选择也是一个道理,你的团队Python最熟就用Python好了,如果最熟悉的是Ruby那就用Ruby好了,编程语言、框架都只是工具,能多、快、好、省的干完活就是好东西,管TMD是日本鬼子还是美帝造呢!</li>
<li>过分关注性能 -
其实大部分人是没必要太关心框架的性能的,因为你开发的网站根本就是个小站,能上1万的IP的网站已经不多了,上10万的更是很少很少。在没有一定的访问量前谈性能其实是没有多大意义的,因为你的CPU和内存一直就闲着呢。而且语言和框架一般也不会是性能瓶颈,性能问题最常出现在数据库访问和文件读写上。PHP的Zend
Framework是出了名的慢,但是Zend
Framework一样有大站,如:digg.com;常被人说有性能问题的Ruby和Rails,不是照样可以开发出twitter吗?再者现在的硬件、带宽成本其实是很低的,特别有了云计算平台后,人力成本才是最贵的,没有上万的IP根本就不用太在意性能问题,流量上去了花点钱买点服务器空间好了,简单快速的解决性能问题。</li>
</ol>
<p>注:前面有网友质疑我“Quora是用Pylons开发的”这样的说法不客观,特说明一下,这里所说的某个网站A是用B开发的,只是指A主要或部分是由B开发的,大家就不要再去纠结A还用C了。</p>
</div>
基于UI Automation的自动化测试工具设计指南2011-01-20T17:17:00+08:002011-01-20T17:17:00+08:00飞龙tag:feilong.me,2011-01-20:/2011/01/ms-ui-automation-tool-design-guide.html<p>说明:以下内容是根据2010年我在公司的一次关于UI
Automation的Workshop上的PPT整理而来,在公司我和几位同事基于UI
Automation开发了一款非常强大的UI自动化测试工具,此工具已经在公司得到广泛运用(有十几个产品采用),用于替代昂贵的、且脚本很难维护的商用软件。此文只探讨UIA相关的一些通用技术和一点点UI自动化测试工具的设计经验,因为保密的需要,涉及到公司的这款测试工具部分此文不做介绍。</p>
<p>在没有MSUIA(Microsoft UI
Automation,以下简称UIA)之前,大家只能通过MSAA(Microsoft Active
Accessibility)、Win32
API等Native的方式来操控Windows控件,要想自己写一个UI自动化测试工具是很难很难的,因此这一领域一直被大厂商所垄断,价格也贵得惊人,不是大的软件公司也是用不起这些工具的(除非盗版),比如QTP、Robot、SilkTest等商用工具。UIA定义了一套全新的、针对UI自动化的接口和模式,以往的Win32和MSAA设计出发点并不是为解决UI自动化(Win32旨在提供的通用开发接口,MSAA技术的初衷则是为了方便残疾人使用Windows
程序),而UIA的设计目的(微软也需要一套技术、工具来自动化测试自己的产品)、以及新引入的模式和接口都完全是针对UI自动化测试的。UIA的出现,让草根UI自动化测试工具成为一种可能,看完本文你若有这样的需求就赶紧自己造一个吧:)</p>
<p>在继续介绍UIA之前,大家需要先熟悉UIA的几个名词术语。</p>
<div class="section" id="uia">
<h2><strong>UIA名词解释</strong></h2>
<div class="section" id="elements">
<h3>Elements</h3>
<p>在UIA里 …</p></div></div><p>说明:以下内容是根据2010年我在公司的一次关于UI
Automation的Workshop上的PPT整理而来,在公司我和几位同事基于UI
Automation开发了一款非常强大的UI自动化测试工具,此工具已经在公司得到广泛运用(有十几个产品采用),用于替代昂贵的、且脚本很难维护的商用软件。此文只探讨UIA相关的一些通用技术和一点点UI自动化测试工具的设计经验,因为保密的需要,涉及到公司的这款测试工具部分此文不做介绍。</p>
<p>在没有MSUIA(Microsoft UI
Automation,以下简称UIA)之前,大家只能通过MSAA(Microsoft Active
Accessibility)、Win32
API等Native的方式来操控Windows控件,要想自己写一个UI自动化测试工具是很难很难的,因此这一领域一直被大厂商所垄断,价格也贵得惊人,不是大的软件公司也是用不起这些工具的(除非盗版),比如QTP、Robot、SilkTest等商用工具。UIA定义了一套全新的、针对UI自动化的接口和模式,以往的Win32和MSAA设计出发点并不是为解决UI自动化(Win32旨在提供的通用开发接口,MSAA技术的初衷则是为了方便残疾人使用Windows
程序),而UIA的设计目的(微软也需要一套技术、工具来自动化测试自己的产品)、以及新引入的模式和接口都完全是针对UI自动化测试的。UIA的出现,让草根UI自动化测试工具成为一种可能,看完本文你若有这样的需求就赶紧自己造一个吧:)</p>
<p>在继续介绍UIA之前,大家需要先熟悉UIA的几个名词术语。</p>
<div class="section" id="uia">
<h2><strong>UIA名词解释</strong></h2>
<div class="section" id="elements">
<h3>Elements</h3>
<p>在UIA里,每一个UI控件即是一个Automation
Element,所有的Elements是存储在一个树状结构中的,Windows的桌面是这颗树的根结点(RootElement)。</p>
</div>
<div class="section" id="tree">
<h3>Tree</h3>
<p>UIA tree就是上面所指的树,每个Application都可以看作是一棵子树。</p>
</div>
<div class="section" id="properties">
<h3>Properties</h3>
<p>Element都有一些属性(Properties),比如Automation
ID、Name、ControlType等,要找到一个控件主要是通过这些的属性来查找的。</p>
</div>
<div class="section" id="control-patterns">
<h3>Control patterns</h3>
<p>在找到一个控件后,对一个控件进行操控的时候就需要用到这个控件支持的控制模式(Control
patterns)了,比如:一个TextBox的ValuePattern可以用来获取TextBox里面的文字。</p>
</div>
<div class="section" id="event">
<h3>Event</h3>
<p>当UI控件有什么变动的时候,可能会触发一些事件(比如:弹出HelpText),如果有Client订阅了这个事件则会收到事件的通知。</p>
</div>
</div>
<div class="section" id="id1">
<h2><strong>UIA的架构</strong></h2>
<p><img alt="image0" src="/static/2011/01/UI_Automation.jpg" style="width: 804px; height: 452px;" /></p>
<p>上图左边那部分叫Client,本文指的是UI自动化测试工具,右边叫Application,指的是被测运用程序。Client和Application在启动的时候都会载入UI
Automation Core(UIAutomationCore.dll),UI自动化测试工具就是通过UI
Automation
Core来操控运用程序的。从这个架构图上也可以看到UIA封装了一些MSAA和Win32的接口、屏蔽了Win32和.NET运用程序的差异,UI
Automation Core对外提供了统一的接口,这也就大大简化了Client这边的实现。</p>
<p>基于UIA这套体系实现UI自动化需要解决的两个核心的问题,一是控件查找(Find
Controls);二是控件操作(Control manipulation),下面对此分别进行介绍。</p>
</div>
<div class="section" id="find-controls">
<h2><strong>控件查找(Find Controls)</strong></h2>
<p>UIA除了提供了最基本的遍历整个UIA
tree的API(TreeWalker)外,另外也提供了一些Build-in的控件查找API。</p>
<div class="section" id="treewalker">
<h3>TreeWalker</h3>
<ul class="simple">
<li>GetFirstChild</li>
<li>GetNextSibling</li>
<li>GetParent</li>
<li>…</li>
</ul>
<p>TreeWalker是标准的对UIA tree的遍历API,它是一切控件查找API的基础。</p>
</div>
<div class="section" id="build-in-finding-scopefilting-conditionapi">
<h3>Build-in Finding(基于scope和filting condition的查找API)</h3>
<ul class="simple">
<li>FindFirst(TreeScope, Condition)</li>
<li>FindAll(TreeScope, Condition)</li>
<li>...</li>
</ul>
<p>UIA自带的这些Build-in的查找API是基于TreeScope和Filting
Condition的,查找控件需要定义一个查找范围和过滤条件。</p>
<ul class="simple">
<li>查找范围(TreeScope)是子结点、子孙结点、父结点等这样的树中的范围定义。</li>
<li>过滤条件(Filting Condition)可以是逻辑条件(AndCondition、
OrCondition、NotCondition等)也可以是属性条件(PropertyCondition)</li>
</ul>
<p>下面是一个最简单的示例,在RootElement桌面下查找子结点里Name属性是“Simple
App”的一个控件,因为是在桌面的子结点(一级),它会是一个Application:</p>
<div class="highlight"><pre><span></span><span class="n">Condition</span> <span class="n">winNameCond</span> <span class="p">=</span> <span class="k">new</span> <span class="n">PropertyCondition</span><span class="p">(</span><span class="n">AutomationElement</span><span class="p">.</span><span class="n">NameProperty</span><span class="p">,</span> <span class="s">"Simple App"</span><span class="p">);</span>
<span class="n">AutomationElement</span> <span class="n">app</span> <span class="p">=</span> <span class="n">AutomationElement</span><span class="p">.</span><span class="n">RootElement</span><span class="p">.</span><span class="n">FindFirst</span><span class="p">(</span><span class="n">TreeScope</span><span class="p">.</span><span class="n">Children</span><span class="p">,</span> <span class="n">winNameCond</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="control-manipulation">
<h2><strong>控件操作(Control manipulation)</strong></h2>
<p>通过上面的Find
Controls找到一个控件后,接下来就是如何操作它实现UI自动化的问题了,比如:点击一个Button,选择一个TreeViewItem等等。下面是一个已做好封装的UITextBox这个控件类里获取TextBox的文字的参考实现:</p>
<div class="highlight"><pre><span></span><span class="k">public</span> <span class="k">virtual</span> <span class="kt">string</span> <span class="nf">GetText</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">object</span> <span class="n">o</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">object</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">Element</span><span class="p">.</span><span class="n">TryGetCurrentPattern</span><span class="p">(</span><span class="n">ValuePattern</span><span class="p">.</span><span class="n">Pattern</span><span class="p">,</span> <span class="k">out</span> <span class="n">o</span><span class="p">))</span>
<span class="p">{</span>
<span class="n">ValuePattern</span> <span class="n">pattern</span> <span class="p">=</span> <span class="n">o</span> <span class="k">as</span> <span class="n">ValuePattern</span><span class="p">;</span>
<span class="k">return</span> <span class="n">pattern</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">Value</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="k">return</span> <span class="s">""</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>如上面的代码所示,控件操作有一个固定的模式,首先尝试获取控件的Control
Pattern,如果控件存在这样的Control
Pattern就通过这个Pattern来操控控件,如果没有则需要自定义这个操作或抛出异常等。</p>
</div>
<div class="section" id="ui">
<h2><strong>UI自动化测试工具设计</strong></h2>
<p>直接基于UIA来实现UI自动化不是不可以,但没有人会这么蛮干。为了获取一个Textbox里的文字这样简单的事情,得到处拷贝上面那段的代码,这是不可取的。所以针对上面说的两个核心的问题,我们需要在UIA上进行一些简化、封装(当然光有这两点是不够的,比如还需要提供一些Native的支持、UI同步、Log等功能,本文对此不做讨论):</p>
<div class="section" id="id2">
<h3>简化、强化控件查找</h3>
<ol class="arabic simple">
<li>简化是指简化控件查找API,为了找一个控件就需要写一大堆的Code来定义这样那样的过滤条件(见控件查找部分的示例代码),如果能用一个简单的字符串就统一所有这些那就方便多了,很负责的说我们就是这么干的,Automation
ID、Name、ControlType、Point、Index、或逻辑、与逻辑、通配符、正则表达式、关键路径查找等杂七杂八的各种数据类型统统放到一个字符串里搞定,这也是我们开发的这个工具非常强大的一个地方。</li>
<li>强化是指强化控件查找功能,UIA
Build-in的查找功能的过滤条件是比较简单的,功能也是非常有限的,比如没有对根据通配符、正则表达式来查找的支持,但是我们可以通过最基本的TreeWalker的API来扩展实现这样的查找功能。</li>
</ol>
</div>
<div class="section" id="id3">
<h3>封装控件的操控</h3>
<p>封装常用控件的基本操作,如:Button的Click、TreeView的Expand和Collapse、Datagrid的操作等等,使控件的操作变成一个简单的API调用,可以考虑把UIA
ControlType里定义的30几种控件中最常用的控件基本操作都实现了,这样写测试脚本的时候就很安逸了。一些产品中可能会使用一些非标的控件,对于这些自定义的控件,用标准控件的操控API可能不管用,通常通过下面两种方式来解决这个问题,一是继承标准控件,重写操控API的实现,如果能够实现的话;二是让开发人员改代码,尽量不要使用非标控件:)</p>
</div>
</div>
<div class="section" id="uiframework">
<h2><strong>UI自动化测试framework设计</strong></h2>
<p>当有了应手的测试工具后,测试脚本的维护依然是个老大难的问题,这个需要有一个好的自动化测试framework来隔离UI的变化,尽量减少维护成本,一个好的framework大体需要有下面几级的分层:</p>
<ol class="arabic simple">
<li>Core -
framework的核心和通用模块,比如:TestCaseBase、Config、WatchDog、Env、OS、DB操作的封装等等。</li>
<li>Dialogs - UI Application、Dialog、Control属性的定义,对于一个大的UI
dialog,为了方便组织是可以考虑切片成一些小的虚拟的Dialogs的。在Dialogs尽量不要涉及操作逻辑,只放属性的定义就可以了。</li>
<li>Key words 或者叫 Wrapper - Key
words是按case(测试用例)层面的需求抽象出来的,大体对应到case里的一个操作步骤,这一个操作步骤实际上可以包含在一个或多个UI
dialogs上的操作组合,比如:用户登录可以是一个Key
word,但它实际上包含了输入用户名、输入密码、点击登录按钮等操作步骤。有了Key
words对UI
Dialog的封装,基本上可以做到在UI变化的时候,只修改Dialogs的定义,Key
words的实现代码很少改动,cases的代码则无需修改(只要case的逻辑没有发生变化)。</li>
<li>Test cases - 到了cases层面问题就变得简单了,就是一些Key
words的简单组合,再加上一些测试结果的验证就OK了。</li>
</ol>
<p>总之,通过UIA实现一套自己的强大的UI自动化测试工具不是不可能,希望本文对一些从事UI自动化测试的同学有所帮助。</p>
<p>扩展资料:</p>
<ul class="simple">
<li><a class="reference external" href="http://en.wikipedia.org/wiki/Microsoft_UI_Automation">http://en.wikipedia.org/wiki/Microsoft_UI_Automation</a></li>
<li><a class="reference external" href="http://blogs.msdn.com/b/lixiong/archive/2009/12/05/ui-automation-under-the-hood.aspx">http://blogs.msdn.com/b/lixiong/archive/2009/12/05/ui-automation-under-the-hood.aspx</a></li>
</ul>
</div>
VMware几个实用技巧2011-01-17T13:41:00+08:002011-01-17T13:41:00+08:00飞龙tag:feilong.me,2011-01-17:/2011/01/vmware-pragmatic-tips.html<p>近日Buzz好友<a class="reference external" href="http://www.google.com/profiles/104231231256400902165">Kyle
Hu</a>同学刚碰到一个关于VM的问题(具体见第三条),借此机会整理一下自己使用VM的几个实用技巧与大家分享。</p>
<div class="section" id="vm">
<h2>1.VM快照管理</h2>
<p>这个功能实在太常用,不用我多废话。这里只是提醒一下还没有用过快照的同学,赶紧的给自己的VM保存点快照吧,这样VM里的系统出了问题或是有其它需要很容易让你还原到原来的某个点,这功能可比Ghost的克隆、恢复真机系统要来的方便的多。快照唯一的毛病就是VM占用的空间大小会急剧增加,是实际增加的空间的好几倍,不知道VMware是怎么搞的。</p>
<p><img alt="image0" class="size-full wp-image-181 aligncenter" src="/static/2011/01/vm-take-snapshot.jpg" style="width: 675px; height: 249px;" /></p>
</div>
<div class="section" id="id1">
<h2>2.扩大硬盘容量</h2>
<p>有时候你可能会遇到原先给定的VM的硬盘空间不够了,这个时候就需要扩大硬盘容量了,如果增加额外的一个硬盘(如下图)能满足需求那问题是比较简单的了。</p>
<p><img alt="image1" class="size-full wp-image-182 aligncenter" src="/static/2011/01/vm-add-hd.jpg" style="width: 659px; height: 474px;" /></p>
<p>但是有时候可能必须要扩大某个已有的硬盘分区(比如原来D盘只有10G,现在必须把D盘扩大到20G),这个时候就需要用到vmware-vdiskmanager.exe(位于VMware安装路径根目录,如:C:\Program
Files\VMware\VMware
Workstation,有些安装版本可能不自带这个,如果没有就去下一个对应的版本吧),vmware-vdiskmanager.exe的帮助信息非常清楚,如下:</p>
<pre class="literal-block">
VMware Virtual Disk Manager - build 34685.
Usage …</pre></div><p>近日Buzz好友<a class="reference external" href="http://www.google.com/profiles/104231231256400902165">Kyle
Hu</a>同学刚碰到一个关于VM的问题(具体见第三条),借此机会整理一下自己使用VM的几个实用技巧与大家分享。</p>
<div class="section" id="vm">
<h2>1.VM快照管理</h2>
<p>这个功能实在太常用,不用我多废话。这里只是提醒一下还没有用过快照的同学,赶紧的给自己的VM保存点快照吧,这样VM里的系统出了问题或是有其它需要很容易让你还原到原来的某个点,这功能可比Ghost的克隆、恢复真机系统要来的方便的多。快照唯一的毛病就是VM占用的空间大小会急剧增加,是实际增加的空间的好几倍,不知道VMware是怎么搞的。</p>
<p><img alt="image0" class="size-full wp-image-181 aligncenter" src="/static/2011/01/vm-take-snapshot.jpg" style="width: 675px; height: 249px;" /></p>
</div>
<div class="section" id="id1">
<h2>2.扩大硬盘容量</h2>
<p>有时候你可能会遇到原先给定的VM的硬盘空间不够了,这个时候就需要扩大硬盘容量了,如果增加额外的一个硬盘(如下图)能满足需求那问题是比较简单的了。</p>
<p><img alt="image1" class="size-full wp-image-182 aligncenter" src="/static/2011/01/vm-add-hd.jpg" style="width: 659px; height: 474px;" /></p>
<p>但是有时候可能必须要扩大某个已有的硬盘分区(比如原来D盘只有10G,现在必须把D盘扩大到20G),这个时候就需要用到vmware-vdiskmanager.exe(位于VMware安装路径根目录,如:C:\Program
Files\VMware\VMware
Workstation,有些安装版本可能不自带这个,如果没有就去下一个对应的版本吧),vmware-vdiskmanager.exe的帮助信息非常清楚,如下:</p>
<pre class="literal-block">
VMware Virtual Disk Manager - build 34685.
Usage: vmware-vdiskmanager.exe OPTIONS diskName \| drive-letter:
Offline disk manipulation utility
Options:
-c : create disk; need to specify other create options
-d : defragment the specified virtual disk
-k : shrink the specified virtual disk
-n <source-disk> : rename the specified virtual disk; need to
specify destination disk-name
-p : prepare the mounted virtual disk specified by
the drive-letter for shrinking
-q : do not log messages
-r <source-disk> : convert the specified disk; need to specify
destination disk-type
-x <new-capacity> : expand the disk to the specified capacity
Additional options for create and convert:
-a <adapter> : (for use with -c only) adapter type (ide, buslogic or lsilogic)
-s <size> : capacity of the virtual disk
-t <disk-type> : disk type id
Disk types:
0 : single growable virtual disk
1 : growable virtual disk split in 2Gb files
2 : preallocated virtual disk
3 : preallocated virtual disk split in 2Gb files
The capacity can be specified in sectors, Kb, Mb or Gb.
The acceptable ranges:
ide adapter : [100.0Mb, 950.0Gb]
scsi adapter: [100.0Mb, 950.0Gb]
ex 1: vmware-vdiskmanager.exe -c -s 850Mb -a ide -t 0 myIdeDisk.vmdk
ex 2: vmware-vdiskmanager.exe -d myDisk.vmdk
ex 3: vmware-vdiskmanager.exe -r sourceDisk.vmdk -t 0 destinationDisk.vmdk
ex 4: vmware-vdiskmanager.exe -x 36Gb myDisk.vmdk
ex 5: vmware-vdiskmanager.exe -n sourceName.vmdk destinationName.vmdk
ex 6: vmware-vdiskmanager.exe -k myDisk.vmdk
ex 7: vmware-vdiskmanager.exe -p m:
(A virtual disk first needs to be mounted at m:
using the VMware Diskmount Utility.)
</pre>
<p>示例ex
4就是一个扩大硬盘分区的例子,找到对应的你要扩大的.vmdk文件照着做就可以了,比如下面是将我的一个VM的D盘扩大到20G(文件路径有空格得用引号“”括一下):</p>
<pre class="literal-block">
vmware-vdiskmanager.exe -x 20Gb
“D:\\09.VM\\build\_vm\\vm\_40\\Windows XP Professional-000001.vmdk”
</pre>
<p>对于Windows系统的VM来说,新增的这部分磁盘空间在VM里暂时是看不到的,需要到系统管理工具里的磁盘管理工具里去分配一下就OK了。</p>
</div>
<div class="section" id="id2">
<h2>3.释放硬盘空间</h2>
<p>VM用的时间一长,有个大毛病就是占用的文件空间越来越大,而实际使用的空间并没有那么多(比如Kyle
Hu遇到的问题:VM分区大小是80GB,使用27GB,虚拟机文件夹为41.9GB,困惑!)。具体原因未明,我的理解可能是因为虚拟硬盘在占用某块空间后,即使这块空间后面被释放了(如:文件删除),VM占用的空间也不能完全缩回去。对于这种情况,如果硬盘吃紧心疼这些被吃掉的空间,就需要用到VM的disk
shrink功能来释放这些空间,关于disk
shrink具体见官方的文档:<a class="reference external" href="http://www.vmware.com/support/ws5/doc/ws_disk_shrink.html">http://www.vmware.com/support/ws5/doc/ws_disk_shrink.html</a>,不过disk
shrink有很多限制条件,比如不能有快照、空间不能被预分配等。要使用disk
shrink需要先安装VMware Tools,安装VMware
Tools需要先将你的VM打开,然后按下图选择安装VMware Tools,</p>
<p><img alt="image2" class="size-full wp-image-184 aligncenter" src="/static/2011/01/vm-install-vm-tools.jpg" style="width: 449px; height: 293px;" /></p>
<p>这样在VM里面就会自动插入一张VMware
Tools的安装盘,VM是Windows系统的话进入光盘安装即可,如果是linux的话,操作步骤大致如下:</p>
<blockquote>
<div class="line-block">
<div class="line"># 到光驱目录</div>
<div class="line">cd /media/cdrom0</div>
<div class="line"># 找到VMware Tools压缩文件</div>
<div class="line">ls</div>
<div class="line"># 解压到TMP文件夹下</div>
<div class="line">tar xvfz VMwareTools-8.1.3-203739.tar.gz -C /tmp</div>
<div class="line">cd /tmp</div>
<div class="line"># 找到VMwareTools安装文件夹</div>
<div class="line">ls</div>
<div class="line">cd vmware-tools-distrib</div>
<div class="line"># 用root权限安装</div>
<div class="line">sudo ./vmware-install.pl</div>
<div class="line"># 输入密码,一路回车,然后就安装完毕了。</div>
<div class="line">#
这个时候应该有<tt class="docutils literal"><span class="pre">vmware-toolbox这个命令了,</span></tt>如果还没有再运行一下vmware-tools-config.pl就OK了。</div>
</div>
</blockquote>
<p>VMware Tools 安装完成后就可以在VM里按上面提供的链接里讲的那样进行disk
shrink了,做完disk
shrink后VM的使用空间和VM文件实际占用的空间基本能保持一致了。</p>
</div>
<div class="section" id="id3">
<h2>4.磁盘碎片整理</h2>
<p>跟真机一样,VM使用时间一长,就会产生很多磁盘碎片,VM的性能会有所下降,这个时候可以通过VM的Defragment来整理磁盘碎片。</p>
<p><img alt="image3" class="size-full wp-image-186 aligncenter" src="/static/2011/01/vm-defragment.jpg" style="width: 644px; height: 555px;" /></p>
<p>磁盘碎片整理结合上面介绍的disk shrink来使用(在disk
shrink之后)效果更佳。</p>
</div>
<div class="section" id="id4">
<h2>5.命令行启动VM</h2>
<p>除了通过界面来操作VM,其实也是可以通过命令行来启动一个VM的(这个可能很少有人用到),比如下面的批处理命令能启动并全屏vm-40这个VM:</p>
<blockquote>
start vmware -X “D:\09.VM\build_vm\vm_40\winxppro.vmx”</blockquote>
<p>你还可以在VM的启动项(如:windows的startup,linux的init.d等)里面预先加入一些自定义的任务,这样就可以自动控制一些VM去做一些事情,完成一些自动化的任务了。</p>
</div>
Python一大好消息PEP 3333 Accepted2011-01-14T08:47:00+08:002011-01-14T08:47:00+08:00飞龙tag:feilong.me,2011-01-14:/2011/01/pep-3333-accepted.html<p>不日前我在<a class="reference external" href="http://feilong.me/2011/01/recommended-entries-for-you-to-master-python">“学好Python必读的几篇文章”</a>中提到的尚在草案状态的<a class="reference external" href="http://www.python.org/dev/peps/pep-3333/">PEP
3333</a>已经正式Final了(Status:Final),公布这个事件的邮件见<a class="reference external" href="http://mail.python.org/pipermail/web-sig/2011-January/004979.html">PEP
3333
Accepted</a>。</p>
<p>这标志着新的兼容Python3的WSGI规范制定工作已完成,此事无疑给Python
Web界和Python3的推广运用注入一强心剂,意义非常重大:</p>
<ol class="arabic simple">
<li><a class="reference external" href="http://www.python.org/dev/peps/pep-0333/">PEP
333</a>和Python3的不兼容让很多Web
server、framework、middleware的开发者不得不对Python3的支持采取观望、等待的态度,暂时没有把项目升级到Python3排上日程。PEP
3333的定稿,将加速这些项目Python3的移植,可以预见的是很快就会有人宣称他们的Web
server或framework将支持PEP
3333、Python3了,届时大家就可以用Python3来写Web运用了。</li>
<li>再扯远一点,当用Python3开发Web已经成为主流的时候,大家就不再为Python2.x和Python3.x的不兼容而犯愁了,这会坚定更多的想用Python开发Web运用的人的决心,Python用户有望进一步的增加,Tiobe上Python语言的指数将再攀新高。</li>
</ol>
<p>PS:快速预览PEP333和PEP3333的差异见:<a class="reference external" href="http://svn.python.org/view/peps/trunk/pep-3333.txt?r1=84854&r2=HEAD">http://svn.python.org/view/peps/trunk/pep-3333 …</a></p><p>不日前我在<a class="reference external" href="http://feilong.me/2011/01/recommended-entries-for-you-to-master-python">“学好Python必读的几篇文章”</a>中提到的尚在草案状态的<a class="reference external" href="http://www.python.org/dev/peps/pep-3333/">PEP
3333</a>已经正式Final了(Status:Final),公布这个事件的邮件见<a class="reference external" href="http://mail.python.org/pipermail/web-sig/2011-January/004979.html">PEP
3333
Accepted</a>。</p>
<p>这标志着新的兼容Python3的WSGI规范制定工作已完成,此事无疑给Python
Web界和Python3的推广运用注入一强心剂,意义非常重大:</p>
<ol class="arabic simple">
<li><a class="reference external" href="http://www.python.org/dev/peps/pep-0333/">PEP
333</a>和Python3的不兼容让很多Web
server、framework、middleware的开发者不得不对Python3的支持采取观望、等待的态度,暂时没有把项目升级到Python3排上日程。PEP
3333的定稿,将加速这些项目Python3的移植,可以预见的是很快就会有人宣称他们的Web
server或framework将支持PEP
3333、Python3了,届时大家就可以用Python3来写Web运用了。</li>
<li>再扯远一点,当用Python3开发Web已经成为主流的时候,大家就不再为Python2.x和Python3.x的不兼容而犯愁了,这会坚定更多的想用Python开发Web运用的人的决心,Python用户有望进一步的增加,Tiobe上Python语言的指数将再攀新高。</li>
</ol>
<p>PS:快速预览PEP333和PEP3333的差异见:<a class="reference external" href="http://svn.python.org/view/peps/trunk/pep-3333.txt?r1=84854&r2=HEAD">http://svn.python.org/view/peps/trunk/pep-3333.txt?r1=84854&r2=HEAD</a></p>
学好Python必读的几篇文章2011-01-12T12:02:00+08:002011-01-12T12:02:00+08:00飞龙tag:feilong.me,2011-01-12:/2011/01/recommended-entries-for-you-to-master-python.html<p>作为脚本语言Python上手容易,但要学好Python能写出一手漂亮的、Pythonic的Python代码并非一日之功,本文的目的在于推荐一些优秀的Python相关的文章(至于书大家可以看dip、learning
python和官方手册去),让你在成长为一名Python高手的路上少走一点弯路。注:文章都是英文的,学好Python读懂英文资料这是必须的了。</p>
<p><a class="reference external" href="http://www.python.org/dev/peps/pep-0008/">1. PEP8 Style Guide for Python Code</a></p>
<p>排第一的当属Python的编码规范PEP8,这个就不用我多说吧,无论是初学还是高手PEP8都是必须烂熟于胸的。在遵循里面讲述的规则的同时,大家也要记住两句比较特殊的话,不过这两句话千万别滥用了:)</p>
<pre class="literal-block">
Two good reasons to break a particular rule:
(1) When applying the rule would make the code less readable, even for
someone who is used to …</pre><p>作为脚本语言Python上手容易,但要学好Python能写出一手漂亮的、Pythonic的Python代码并非一日之功,本文的目的在于推荐一些优秀的Python相关的文章(至于书大家可以看dip、learning
python和官方手册去),让你在成长为一名Python高手的路上少走一点弯路。注:文章都是英文的,学好Python读懂英文资料这是必须的了。</p>
<p><a class="reference external" href="http://www.python.org/dev/peps/pep-0008/">1. PEP8 Style Guide for Python Code</a></p>
<p>排第一的当属Python的编码规范PEP8,这个就不用我多说吧,无论是初学还是高手PEP8都是必须烂熟于胸的。在遵循里面讲述的规则的同时,大家也要记住两句比较特殊的话,不过这两句话千万别滥用了:)</p>
<pre class="literal-block">
Two good reasons to break a particular rule:
(1) When applying the rule would make the code less readable, even for
someone who is used to reading code that follows the rules.
(2) To be consistent with surrounding code that also breaks it (maybe for
historic reasons) -- although this is also an opportunity to clean up
someone else's mess (in true XP style).
</pre>
<p>如果要写Python的C扩展库,你还必须好好学习下<a class="reference external" href="http://www.python.org/dev/peps/pep-0007/">PEP7</a>。</p>
<p><a class="reference external" href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html">2. Code Like a Pythonista: Idiomatic
Python</a></p>
<p>文如其名,本文篇幅较长,但非常非常实用。本文介绍了一系列Python约定俗成的用法和技巧,学习本文能让你写出来的Python代码马上上一个档次,让你成为一个真正的Pythoneer。</p>
<p><a class="reference external" href="http://www.python.org/dev/peps/pep-0318/">3. PEP318 Decorators for Functions and
Methods</a></p>
<p>在Python的世界里decorator是非常常见的,常见的比如auth、cache都会提供decorator,decorator所实现的功能就是修改紧接
decorator之后定义的函数和方法,你可以根据自己的需要给一个已有的函数和方法添油加醋。</p>
<p><a class="reference external" href="http://docs.python.org/library/re.html">4. Python regular expression documentation</a></p>
<p>掌握正则表达式是编程人员的必备技能,这是re模块的官方文档,用到正则表达式的时候要常来翻翻。Python的正则表达式跟别的语言函数用法有点
不一样,因此也有人抱怨说Python的re模块不好用,文章开头关于正则表达式规则部分可以当正则表达式的入门教材,如果你还不知道正则表达式是个什么
东西的话。个人觉得Python的re模块非常强大的,举个有点意思的例子,比如VERBOSE的正则表达式还支持在正则表达式中间加注释说明正则表达式
的具体含义,因为正则表达式通常都象天书一样比较难懂,因此这个功能显得非常有用。</p>
<div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">"""\d + # the integral part</span>
<span class="s2"> \. # the decimal point</span>
<span class="s2"> \d * # some fractional digits"""</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">X</span><span class="p">)</span>
</pre></div>
<p><a class="reference external" href="http://www.python.org/dev/peps/pep-0333/">5. PEP333 Python Web Server Gateway Interface
v1.0</a></p>
<p>如果你要用Python来做Web相关的开发(对大多说人来说主要就是指Web运用)WSGI是必读的,WSGI是Python
web server、application、middleware之间的官方规范标准,现在主流的Python
web
server和framework都肯定支持WSGI的。只有了解了WSGI你才能更好的理解Python的web
framework的工作机制、middleware为啥可以串联起来、web server是怎么跟web
application交互的。WSGI有两个为人诟病的地方,一是不支持异步,Tornado是一个异步的Web
server,但是若要在上面运行WSGI的framework如Django,则Tornado的异步特性完全用不上;二是WSGI
v1.0不支持Python3.x,为了支持Python3.x,有两篇还在Draft状态的PEP文档<a class="reference external" href="http://www.python.org/dev/peps/pep-3333/">PEP3333</a>和<a class="reference external" href="http://www.python.org/dev/peps/pep-0444/">PEP444</a>可供参考。</p>
<p><a class="reference external" href="http://scotdoyle.com/python-epoll-howto.html">6. How To Use Linux epoll with
Python</a></p>
<p>更深入一点,如果你要做服务器端的编程的话,此文可以让你深入理解Python的同步、异步socket编程模式。假如你觉得Tornado的源码比较费解的话,读读这篇文章对你会很有大的帮助。</p>
<p>7.另外还有一些比较重要的文档,这里不做详解,有兴趣的同学可以去看看:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.siafoo.net/article/52">Python Tips, Tricks, and Hacks</a></li>
<li><a class="reference external" href="http://www.python.org/dev/peps/pep-0257/">Python Docstring</a></li>
<li><a class="reference external" href="http://www.python.org/dev/peps/pep-0342/">Coroutines via Enhanced
Generators</a></li>
<li><a class="reference external" href="http://packages.python.org/greenlet/">Greenlet documentation</a></li>
<li><a class="reference external" href="http://www.python.org/download/releases/2.2.3/descrintro/">Unifying types and classes in
Python</a>(要翻墙)</li>
<li><a class="reference external" href="http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html">Python Attributes and
Methods</a></li>
<li><a class="reference external" href="http://www.cafepy.com/article/python_types_and_objects/">Python Types and
Objects</a>,中文版见:<a class="reference external" href="http://wiki.woodpecker.org.cn/moin/PyTypesAndObjects">http://wiki.woodpecker.org.cn/moin/PyTypesAndObjects</a></li>
<li><a class="reference external" href="http://www.fantascienza.net/leonardo/ar/python_best_practices.html">Python best
practices</a></li>
<li><a class="reference external" href="http://artifex.org/~hblanks/talks/2011/pep20_by_example.py.txt">PEP 20 (The Zen of Python) by
example</a></li>
<li><a class="reference external" href="http://google-styleguide.googlecode.com/svn/trunk/pyguide.html">Google Python
Guide</a></li>
<li><a class="reference external" href="http://stackoverflow.com/questions/101268/hidden-features-of-python">Hidden features of Python</a></li>
<li>待补充..,欢迎大家推荐。</li>
</ul>
说说Python获年度Tiobe编程语言大奖这事2011-01-10T18:36:00+08:002011-01-10T18:36:00+08:00飞龙tag:feilong.me,2011-01-10:/2011/01/python-wins-tiobe-2010-pro-lang-award.html<p>今天在reddit的feed里看到了Python获得了2010年编程语言大奖,国外也有不少朋友在讨论这事,我也顺带来说几句。</p>
<p>Python在2010年获得了较大的市场份额增长,2010年1月以来Python的市场份额增长了1.81%,是增长速度最快的,其次是Objective
-
C(1.63%)。排名见下表,详情请见Tiobe原址:<a class="reference external" href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html</a>。</p>
<p><img alt="image0" class="size-full wp-image-118 aligncenter" src="/static/2011/01/python_tiobe_index_2010_winner.jpg" style="width: 598px; height: 582px;" /></p>
<p>再来看一下历年的获奖语言:</p>
<p><img alt="image1" class="size-full wp-image-119 aligncenter" src="/static/2011/01/python_lang_wins_years.jpg" style="width: 144px; height: 215px;" /></p>
<p>Python在2007和2010最近的这几年里获得两次年度大奖,确实是很给力。</p>
<p>虽然Tiobe的排名不是非常靠谱,大家对此排行争议也很多,但大体它还是可以反映一个趋势。Python除了保持在后台脚本、测试领域的优势外,最近几年随着Python
web
framework的蓬勃发展,Python在Web领域的运用也越来越多,国外出现了一大批用Python开发的新站、大站,比如大名鼎鼎的:<a class="reference external" href="http://www.reddit.com">reddit.com</a>、<a class="reference external" href="http://www.dropbox.com">dropbox.com</a>、<a class="reference external" href="http://bitbucket.org">bitbucket.org</a>、<a class="reference external" href="http://www.quora.com">quora.com</a>、<a class="reference external" href="http://friendfeed.com">friendfeed.com</a>,其中reddit代码还是开源的 …</p><p>今天在reddit的feed里看到了Python获得了2010年编程语言大奖,国外也有不少朋友在讨论这事,我也顺带来说几句。</p>
<p>Python在2010年获得了较大的市场份额增长,2010年1月以来Python的市场份额增长了1.81%,是增长速度最快的,其次是Objective
-
C(1.63%)。排名见下表,详情请见Tiobe原址:<a class="reference external" href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html</a>。</p>
<p><img alt="image0" class="size-full wp-image-118 aligncenter" src="/static/2011/01/python_tiobe_index_2010_winner.jpg" style="width: 598px; height: 582px;" /></p>
<p>再来看一下历年的获奖语言:</p>
<p><img alt="image1" class="size-full wp-image-119 aligncenter" src="/static/2011/01/python_lang_wins_years.jpg" style="width: 144px; height: 215px;" /></p>
<p>Python在2007和2010最近的这几年里获得两次年度大奖,确实是很给力。</p>
<p>虽然Tiobe的排名不是非常靠谱,大家对此排行争议也很多,但大体它还是可以反映一个趋势。Python除了保持在后台脚本、测试领域的优势外,最近几年随着Python
web
framework的蓬勃发展,Python在Web领域的运用也越来越多,国外出现了一大批用Python开发的新站、大站,比如大名鼎鼎的:<a class="reference external" href="http://www.reddit.com">reddit.com</a>、<a class="reference external" href="http://www.dropbox.com">dropbox.com</a>、<a class="reference external" href="http://bitbucket.org">bitbucket.org</a>、<a class="reference external" href="http://www.quora.com">quora.com</a>、<a class="reference external" href="http://friendfeed.com">friendfeed.com</a>,其中reddit代码还是开源的。有趣的是,虽然在Python的Web开发领域<a class="reference external" href="http://www.djangoproject.com">Django</a>大红大紫,但是这五个网站中只有bitbucket一个是用Django开发的,而且问题还特多(碰到500错误是常态,最近似乎稳定些了),另外有三个用的是相对小众的<a class="reference external" href="http://www.pylonshq.com">Pylons</a>,而friendfeed用的则是friendfeed自己写的<a class="reference external" href="http://www.tornadoweb.org">Tornado</a>(网站需翻墙)。虽然Python语言的前景一片大好,但我个人认为目前也有一些问题待解决的:</p>
<ol class="arabic simple">
<li>Python web
framework多如牛毛(不完全列表见:<a class="reference external" href="http://wiki.python.org/moin/WebFrameworks">http://wiki.python.org/moin/WebFrameworks</a>),Python界需要出现一个具有垄断地位的Web
framework,我认为Django还不够。Web
framework一多,好处是你可以有更多的选择自由,甚至一个framework本身还是高度可定制的(如:Pylons);不好的地方则是很多时候你不知道该选哪一个,特别新手往往要在framework之间左右摇摆好久,从我们常常看到“是选Django呢还是Pylons呢”这类的提问和争论就可知一般(不管是国内还是国外),另外这样也不利于知识的分享,因为知识点比较分散。好在现在Python界正在尝试做一些融合,<a class="reference external" href="http://bfg.repoze.org/">repoze.bfg</a>已经开始合并到Pylons这个大的project中了。具体可以看看:<a class="reference external" href="http://lists.repoze.org/pipermail/repoze-dev/2010-November/003619.html">http://lists.repoze.org/pipermail/repoze-dev/2010-November/003619.html</a>
和
<a class="reference external" href="http://be.groovie.org/post/1558848023/notes-on-the-pylons-repoze-bfg-merger">http://be.groovie.org/post/1558848023/notes-on-the-pylons-repoze-bfg-merger</a>
(后者要翻墙)。不知道合并后的Pylons能否达到Rails在Ruby的Web开发领域中那样的统治地位,虽然我看好Pylons但是我觉得在Python的世界里这个会很难,因为有了<a class="reference external" href="http://www.python.org/dev/peps/pep-0333/">WSGI规范(PEP333)</a>用Python自己造一个Web的轮子实在太简单了,你我都有能力写一个:)</li>
<li>Python2.x和Python3.x差异挺大、前后不兼容,虽然有2to3的工具可以转,但不能解决所有的问题。Python3.x尚未完全普及开来,很多第三方的库都没用官方支持Python3.x。考虑到前后版本的这个不兼容性,这会让一些人对采用Python开发项目产生顾忌。而在Web开发领域,WSGI1.0也是不支持Python3.x,支持Python3.x的<a class="reference external" href="http://www.python.org/dev/peps/pep-0444/">Web3(PEP444)</a>还处在草案状态。</li>
</ol>
<p>虽然有上面所说的一些问题,但是可以预见的是,随着Python3.x的普及和Python
web
framework的发展、成熟,Python依然有很大的上涨空间,我认为将来(最多5年吧)超过PHP是很有可能的,祝Python一路走好。</p>
<p>另外,我新注册了域名<a class="reference external" href="http://www.chinapy.org">chinapy.org</a>(现在还不能访问),准备弄一个开放一点的中国的Python社区,给Python在中国的推广运用做点自己的贡献。</p>
域名注册的那点事2011-01-10T14:04:00+08:002011-01-10T14:04:00+08:00飞龙tag:feilong.me,2011-01-10:/2011/01/something-about-domain-registration.html<p>要架设一个商业网站、个人博客,首要的即是要注册一个好的域名(大家也都知道kaixin001.com和kaixin.com那点事),而要注册一个好的域名特别是
.com
的也不是那么容易。鉴于我现在都快成“域名控”了,也积累了一些关于域名注册查询、域名注册、域名抢注的经验,特写博一篇与大家分享一下域名注册的那点事。</p>
<div class="section" id="id2">
<h2>1.注册查询</h2>
<p>域名注册网站大都会提供域名注册查询的功能,但功能可能会比较简单,比如新网互联的,而有些会提供域名联想、域名建议等附加功能,比如万网的。而真正查询功能比较强大的是<a class="reference external" href="http://www.domaintools.com/">http://www.domaintools.com</a>,我在注册域名前都会到domaintools先查询一下,然后去注册。</p>
<p>举例来说,假设我要查询以字符串fei开头的,不带数字和“-”且字符总数在8个以内的已删除的可注册的域名,下面的链接即实现了这一功能:</p>
<p><a class="reference external" href="http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search">http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B …</a></p></div><p>要架设一个商业网站、个人博客,首要的即是要注册一个好的域名(大家也都知道kaixin001.com和kaixin.com那点事),而要注册一个好的域名特别是
.com
的也不是那么容易。鉴于我现在都快成“域名控”了,也积累了一些关于域名注册查询、域名注册、域名抢注的经验,特写博一篇与大家分享一下域名注册的那点事。</p>
<div class="section" id="id2">
<h2>1.注册查询</h2>
<p>域名注册网站大都会提供域名注册查询的功能,但功能可能会比较简单,比如新网互联的,而有些会提供域名联想、域名建议等附加功能,比如万网的。而真正查询功能比较强大的是<a class="reference external" href="http://www.domaintools.com/">http://www.domaintools.com</a>,我在注册域名前都会到domaintools先查询一下,然后去注册。</p>
<p>举例来说,假设我要查询以字符串fei开头的,不带数字和“-”且字符总数在8个以内的已删除的可注册的域名,下面的链接即实现了这一功能:</p>
<p><a class="reference external" href="http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search">http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search</a></p>
<p>这个查询功能提供了常用的过滤选项,方便好用,能帮助你快速找到合适的且可注册的域名。不过domaintools的这个功能在翻页时有时会有点小问题,如在上面的链接页面点击进入结果的第8页:</p>
<p><a class="reference external" href="http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search&time=20110109190538-20&page=8">http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search&time=20110109190538-20&page=8</a></p>
<p>你可能已经发现了,这个时候的过滤条件是不管用的,搜出的结果并不符合上面设定的条件,经过多次摸索实践,我发现解决问题的办法其实也很简单,就是去掉url中的的time部分(&time=20110109190538-20)变成下面这个样子就好了。</p>
<p><a class="reference external" href="http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search&page=8">http://domain-search.domaintools.com/?q=fei&bc=8&bh=B&order=left&pool=B&filter=y&search_type=&rows=100&de_search=Search&page=8</a></p>
<p>domaintools同时还提供域名状态监控(monitor)的功能,只要你在<a class="reference external" href="http://www.domaintools.com/monitor/">http://www.domaintools.com/monitor/</a>添加上你想关注的域名,比如你要监控feilong.me,那么一旦feilong.me的域名状态发生了变化(如:状态由OK进入了赎回期),domaintools就会给你发邮件通知,这个是要结合后面将要介绍的域名抢注来用的。我就利用domaintools的这个功能关注了很多感兴趣的域名。</p>
</div>
<div class="section" id="id3">
<h2>2.域名注册</h2>
<p>国外域名注册首选<a class="reference external" href="http://www.godaddy.com">Godaddy.com</a>或<a class="reference external" href="http://www.name.com">name.com</a>,两者的价格差不多,Godaddy的优惠码网上比较好找(搜
Godaddy优惠码
即可),而name.com可注册的域名比Godaddy的多,比如Godaddy上是不能注册.im、.io的域名的,我最近就是为了注册一个.im的域名就用到了name.com。</p>
<p>但是Godaddy注册域名时有很多垃圾干扰的信息弹出来(这些多是要额外收费的),好在最近Godaddy推出了快速支付通道选项,方便了许多,没以前那么讨厌了,而且现在Godaddy也支持用国内的支付宝支付了。</p>
<p>这里另附几个最最常用的且长期有效的Godaddy优惠码(可以省一点$):</p>
<ul class="simple">
<li>不同后缀续费价格不同(ICANN另外要收$0.18域名登记费)
优惠码: cjc695dom 说明: $7.49 .COM 注册,续费
优惠码: cjctld749 说明: $7.49 .NET 注册,续费
优惠码: cjctld749 说明: $7.49 .ORG 注册,续费</li>
<li>另外这里长期提供Goddady的优惠码,<a class="reference external" href="http://www.retailmenot.com/view/godaddy.com">http://www.retailmenot.com/view/godaddy.com</a></li>
</ul>
<p>至于国内提供域名注册的网站则多如牛毛,我自己就在好几家注册过域名,根据我的经验我推荐<a class="reference external" href="http://www.dns.com.cn/">新网互联</a>。</p>
<p>国内域名注册价格差距比较大,以.com域名为例,少的50多则130块,但是在一些小的公司注册域名可能会碰到好多问题,比如:</p>
<ol class="arabic simple">
<li>域名管理没有添加txt记录的功能(如果需要建立自己的邮件服务器的话,这个是必须的,不然你网站发的邮件很容易进别人的垃圾箱),就这一条很多注册商就不合格;</li>
<li>新网互联的域名记录更新几乎是即时的,比如你添加一条A记录,马上就可以生效,而很多公司的是要在24小时内生效的;</li>
<li>哪天若想转出域名他们收你的费用不说,流程还会非常麻烦。</li>
</ol>
<p>关于这些问题就不点名批评哪个小公司了,反正我是深受其害,至今仍然有一个域名挂在一家小公司那,让我一直耿耿于怀。</p>
<p>新网互联注册域名就是费用稍微有点贵,130块/1年,比国外的Godaddy的$7.67贵不少。</p>
<p><strong>特别说明:</strong>目前在国外注册的域名似乎没办法备案或备案非常麻烦(若接入商有实力帮你搞定),这个具体如何我现在也不是很确定,了解的可以回帖补充下。</p>
</div>
<div class="section" id="id4">
<h2>3.域名抢注</h2>
<p>如果你看中某个域名,不巧的是域名已注册,巧的是这个域名至今还没有续费,已进入了赎回期或删除期,这个时候你就有机会抢注这个域名了。域名抢注最有名的网站当属<a class="reference external" href="http://www.pool.com">pool.com</a>(60美元起步价),在pool.com你还可以查到一个域名预计的删除日期,关于域名删除详细解释见下。</p>
<ol class="arabic simple">
<li>假如域名feilong.me到期时间为2010年02月01日;</li>
<li>从2010年02月02日开始,域名的ns将会被系统自动删除,域名无法解析,注册公司会继续保留该域名30天,用户可以在这30天的期限内续费;</li>
<li>如果在2所述的30天期限内没有续费,即从2010年02月28日开始,域名将变成RedemptionPeriod状态,该状态将会保持30天,在此期间该域名不会掉下来,但是除了restore命令以外的所有命令对此域名无效;</li>
<li>域名在RedemptionPeriod状态下可以restore回来,但每restore一次需要支付费用;</li>
<li>如果域名在RedemptionPeriod状态下的30天没有restore,从2010.03.29开始域名变成PendingDelete状态(5天),2010年04月04日该域名将会删除。大约域名从到期到掉下来要30+30+5=65天。</li>
<li>至于域名删除的具体时间,精确删除时间是不确定的带有很大的随机性,但也存在着一些普遍规律。例如,国际域名的删除时间,集中在删除日期的第二天(因为有时差,上面的例子就会是2010年04月05日)北京时间早上
2 点到 4点 (夏时制是
2点到3点,非夏时制是3点到4点)。如果过了这个时段,你还没发现域名掉下来,请不要存在侥幸心理,其实很有可能已经被其它人在第一时间抢注了。要是你抢的域名比较一般的,那么几天内你还有机会再次见到可以注册的可能,因为普通域名有可能是别人一时冲动注册了,然后再删除掉的。国内域名的删除时间,通常在域名到期后的第15或16天,早上4:30准时删除。目前还没有专门提供国内域名完全删除列表的网站,基本上有很多好域名掉到没人知道:),这就意味着只要你运气好,手工注册也存在抢到好域名的可能。(我就有两个很好的域名是手动抢来的,而不是通过pool.com)</li>
</ol>
<p>BTW:话说注册域名这事似乎会上瘾,中毒的也不止我一个,至于解毒的办法也很简单,就是在host里把常去的域名注册网站都定向到127.0.0.1吧:)</p>
</div>
Kindle中文乱码问题(TXT、PDF)解决办法2011-01-08T11:46:00+08:002011-01-08T11:46:00+08:00飞龙tag:feilong.me,2011-01-08:/2011/01/solve-kindle-cn-encoding-problem.html<p><strong>问题一:文件名、TXT文档、上网等中文变成一个个“口”字问题</strong>(已解决的请直接跳到第二条,我这主要记录一下给自己留个底,这部分的内容主要来自网络)</p>
<p>Amazon官方说kindle支持简体中文和繁体中文,事实上也算支持了,但中文支持还是很差,简体中文却大部分无法正常显示,变成“口”字了。这个是因为语言设置(locale)的问题,解决办法很简单,就是改变默认的语言设置,输入以下命令即可:</p>
<div class="line-block">
<div class="line">;debugOn</div>
<div class="line">~changeLocale zh-CN</div>
<div class="line">;debugOff</div>
</div>
<p>输入时要注意大小写,具体输入步骤是:在home页面,先按下回车(也就是方向键旁边那个弯弯箭头键),会出现一个输入框,输入第一条命令后,回车,再输入第二条,再回车,再第3条回车。这样就设置成功了,然后重启kindle。</p>
<p>重启步骤:home -> Menu -> Settings -> Menu -> Restart</p>
<p>也就是进入设置那里再按MENU选择restart重启,或者直接滑动那个关机键按住15秒左右就重启了。</p>
<p>重启之后没问题的话,中文显示应该没问题了,不过txt文件支持还是会有些问题 …</p><p><strong>问题一:文件名、TXT文档、上网等中文变成一个个“口”字问题</strong>(已解决的请直接跳到第二条,我这主要记录一下给自己留个底,这部分的内容主要来自网络)</p>
<p>Amazon官方说kindle支持简体中文和繁体中文,事实上也算支持了,但中文支持还是很差,简体中文却大部分无法正常显示,变成“口”字了。这个是因为语言设置(locale)的问题,解决办法很简单,就是改变默认的语言设置,输入以下命令即可:</p>
<div class="line-block">
<div class="line">;debugOn</div>
<div class="line">~changeLocale zh-CN</div>
<div class="line">;debugOff</div>
</div>
<p>输入时要注意大小写,具体输入步骤是:在home页面,先按下回车(也就是方向键旁边那个弯弯箭头键),会出现一个输入框,输入第一条命令后,回车,再输入第二条,再回车,再第3条回车。这样就设置成功了,然后重启kindle。</p>
<p>重启步骤:home -> Menu -> Settings -> Menu -> Restart</p>
<p>也就是进入设置那里再按MENU选择restart重启,或者直接滑动那个关机键按住15秒左右就重启了。</p>
<p>重启之后没问题的话,中文显示应该没问题了,不过txt文件支持还是会有些问题,只有utf-8编码的文件能正常显示并打开,但读了几页后就又出现乱码了,这个问题似乎没能够解决。只能发送邮件到name@kindle.com(name是你的kindle账号)来转换格式了,或者用calibre等转换工具转换成MOBI格式了。</p>
<p><strong>问题二:部分中文PDF文档乱码或是空白</strong></p>
<p>这个则是因为Kindle里缺少该PDF文件所采用的字体,解决的办法是加入软字体重新打印生成新PDF文件,具体做法如下:</p>
<ol class="arabic simple">
<li>打开PDF文档后选择打印,注意要选择选择<strong>打印到PDF而不是打印机</strong></li>
</ol>
<p><img alt="image0" class="alignnone size-medium wp-image-100" src="/static/2011/01/pdf_print-265x300.jpg" style="width: 265px; height: 300px;" /></p>
<p>2.打印选项设置(进打印后选择属性),然后在纸张/质量(Paper/Quality)里选择高级选项(Advanced),再选择下载软字体,如下:</p>
<p><img alt="image1" class="alignnone size-medium wp-image-101" src="/static/2011/01/224_59455_0478d4526e287dc-288x300.jpg" style="width: 288px; height: 300px;" /></p>
<p>3.
开始打印,选择保存文件的路径,打印开始后会有打印页面进度显示,打印生成新的PDF文件就OK了,新的文件传Kindle里就不再乱码了。</p>
<p>BTW:</p>
<ol class="arabic simple">
<li>如果PDF文档锁定了,不允许打印(打印按钮是灰的),这个时候你需要用工具将PDF文件解锁,SysTools
PDF
Unlocker(<a class="reference external" href="http://www.piaoxu.net/12949.html">http://www.piaoxu.net/12949.html</a>)可以解决这个问题。</li>
<li>有个别文档打印到文件时会出现异常无法打印全部页面的情况,比如共600页,打印出来(生成)的PDF文件只有400页,解决办法就是选择打印页面重新打印后面一部分内容(401-600页),然后用Adobe
Acrobat Pro将两个文件重新合成为一个文件。</li>
</ol>
亚马逊AWS(EC2)资源汇总2011-01-01T21:54:00+08:002011-01-01T21:54:00+08:00飞龙tag:feilong.me,2011-01-01:/2011/01/amazon-aws-ec2-guide.html<p>亚马逊AWS全称Amazon Web
Services,即亚马逊于2006年推出的云计算服务,核心产品包括EC2、S3、EBS、CloudFront、SimpleDB等,全部产品列表见:<a class="reference external" href="http://aws.amazon.com/products/">http://aws.amazon.com/products/</a>。</p>
<p>从2010年11月1日开始,亚马逊还推出了一个免费<a class="reference external" href="http://aws.amazon.com/free/">AWS Free Usage
Tier</a>体验活动,相当于613
MB的VPS,可以免费(部分超额的使用还是要收费的)使用一年。</p>
<p>在国外AWS居领导地位,很多大站、新站都用了AWS的服务,比如<a class="reference external" href="http://twitter.com">Twitter</a>、<a class="reference external" href="http://bitbucket.org">Bitbucket</a>、<a class="reference external" href="http://www.quora.com">Quora</a>,而在国内可能知道的、用过AWS的人并不多。我也是在<a class="reference external" href="http://www.andapponline.com">James
Zhang</a>同学不停的鼓动下最终用上了AWS的,<a class="reference external" href="http://feilong.me">飞龙札记</a>和我的<a class="reference external" href="http://poweredsites.org">http://poweredsites.org</a>就是部署在AWS上,下面是我收集的一些关于AWS的资源汇总:</p>
<p>AWS官方的文档入口</p>
<ul class="simple">
<li><a class="reference external" href="http://aws.amazon.com/documentation/">http://aws …</a></li></ul><p>亚马逊AWS全称Amazon Web
Services,即亚马逊于2006年推出的云计算服务,核心产品包括EC2、S3、EBS、CloudFront、SimpleDB等,全部产品列表见:<a class="reference external" href="http://aws.amazon.com/products/">http://aws.amazon.com/products/</a>。</p>
<p>从2010年11月1日开始,亚马逊还推出了一个免费<a class="reference external" href="http://aws.amazon.com/free/">AWS Free Usage
Tier</a>体验活动,相当于613
MB的VPS,可以免费(部分超额的使用还是要收费的)使用一年。</p>
<p>在国外AWS居领导地位,很多大站、新站都用了AWS的服务,比如<a class="reference external" href="http://twitter.com">Twitter</a>、<a class="reference external" href="http://bitbucket.org">Bitbucket</a>、<a class="reference external" href="http://www.quora.com">Quora</a>,而在国内可能知道的、用过AWS的人并不多。我也是在<a class="reference external" href="http://www.andapponline.com">James
Zhang</a>同学不停的鼓动下最终用上了AWS的,<a class="reference external" href="http://feilong.me">飞龙札记</a>和我的<a class="reference external" href="http://poweredsites.org">http://poweredsites.org</a>就是部署在AWS上,下面是我收集的一些关于AWS的资源汇总:</p>
<p>AWS官方的文档入口</p>
<ul class="simple">
<li><a class="reference external" href="http://aws.amazon.com/documentation/">http://aws.amazon.com/documentation/</a></li>
</ul>
<p>EC2入门文档</p>
<ul class="simple">
<li>Amazon官方的(有这个基本就够了):<a class="reference external" href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/">http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/</a></li>
<li>Ubuntu官方上的:<a class="reference external" href="https://help.ubuntu.com/community/EC2StartersGuide">https://help.ubuntu.com/community/EC2StartersGuide</a></li>
</ul>
<p>EC2使用价格表:</p>
<ul class="simple">
<li><a class="reference external" href="http://aws.amazon.com/ec2/pricing/">http://aws.amazon.com/ec2/pricing/</a></li>
</ul>
<p>Ubuntu官方的EC2 AMI</p>
<ul class="simple">
<li>Ubuntu AMI入口:<a class="reference external" href="http://uec-images.ubuntu.com/releases">http://uec-images.ubuntu.com/releases</a></li>
<li>Ubuntu 9.10:<a class="reference external" href="http://uec-images.ubuntu.com/releases/9.10/release/">http://uec-images.ubuntu.com/releases/9.10/release/</a></li>
<li>Ubuntu 10.10:<a class="reference external" href="http://uec-images.ubuntu.com/releases/10.10/release/">http://uec-images.ubuntu.com/releases/10.10/release/</a></li>
</ul>
<p>EC2的firefox插件(可管理你的EC2,非常好用、方便)</p>
<ul class="simple">
<li><a class="reference external" href="http://sourceforge.net/projects/elasticfox/">http://sourceforge.net/projects/elasticfox/</a></li>
</ul>
<p>AWS的Python工具boto</p>
<ul class="simple">
<li><a class="reference external" href="http://boto.cloudhackers.com/">http://boto.cloudhackers.com/</a></li>
</ul>
<p>另外提供一些中文资料</p>
<ul class="simple">
<li><a class="reference external" href="http://www.5558.biz/a/jianzhanjishu/tuwenjiaocheng/Amazon-freeVPS.html">http://www.5558.biz/a/jianzhanjishu/tuwenjiaocheng/Amazon-freeVPS.html</a></li>
<li><a class="reference external" href="http://blog.csdn.net/lkhdmail/archive/2008/12/08/3477597.aspx">http://blog.csdn.net/lkhdmail/archive/2008/12/08/3477597.aspx</a></li>
<li><a class="reference external" href="http://www.chinacloud.cn/show.aspx?id=2347&cid=12">http://www.chinacloud.cn/show.aspx?id=2347&cid=12</a></li>
</ul>
<p>至于如何玩转一个EC2
instance其实跟玩一般的VPS没什么两样,可以参考slicehost上面的相关文档(slicehost的文档非常全且浅显易懂),如:<a class="reference external" href="http://articles.slicehost.com/2010/10/18/ubuntu-maverick-setup-part-1">http://articles.slicehost.com/2010/10/18/ubuntu-maverick-setup-part-1</a></p>
<p>最后附上一重磅级的材料,<a class="reference external" href="http://www.andapponline.com">James
Zhang</a>同学的<a class="reference external" href="/static/2010/12/Amazon-AWS-introduction-by-James-Zhang.pdf">Amazon AWS introduction
by James
Zhang</a>的英文PPT(方便阅读已转成PDF),版权归James同学,这里已征得James同学本人同意贴到本篇博客里,PDF文件地址:<a class="reference external" href="/static/2010/12/Amazon-AWS-introduction-by-James-Zhang.pdf">/static/2010/12/Amazon-AWS-introduction-by-James-Zhang.pdf</a>。</p>
免输入FTP信息自动升级WordPress2010-12-31T21:04:00+08:002010-12-31T21:04:00+08:00飞龙tag:feilong.me,2010-12-31:/2010/12/auto-update-wordpress-without-ftp-auth.html<p>WordPress的3.0.4
修复了一个严重的<a class="reference external" href="http://cn.wordpress.org/2010/12/30/3-0-4-update/">安全漏洞</a>,所以赶紧着手升级飞龙札记的WordPress版本,在管理后台的“更新”页面点击“自动升级”很快就完成了自动更新,系统已成功升级到了3.04。</p>
<p>但是,同样的等我跑去升级<a class="reference external" href="http://17weiguan.com">围观网</a>的时候,却要求我输入FTP信息(主机、用户名、密码等),什么原因造成两者升级的不同呢?</p>
<ol class="arabic simple">
<li>飞龙札记和围观网是运行在两台不同的服务器上,但都是用nginx
proxy到后台的PHP
fastcgi进程进行处理的,服务器的配置基本一致,而两个网站用的WordPress文件是一样的,所以首先就可以排除WordPress版本和服务器配置的差异引起的不同。</li>
<li>两个网站的差别主要体现在主题和插件,这些虽然牵涉到WordPress的设置但是跟WordPress本身及插件升级根本没关系,所以也基本可以排除由WordPres设置差异造成两者升级差异的可能性。</li>
<li>而要求输入FTP信息,目的其实是为了下载WordPress升级文件。两个站一个可以自己下,另一个则要提供FTP账户信息,由此看来应该是文件夹权限问题造成的,仔细对比了一下飞龙札记和围观网的代码文件夹权限,发现飞龙札记的代码文件夹所有者和fastcgi进程的用户是同一个,而围观网的则是两个不同的用户。将围观网的代码文件夹所有者改成fastcgi的进程用户(sudo
chown -R fastcgi-username
/home/local/weiguan),问题解决,围观网自动升级不再需要输入FTP信息了 …</li></ol><p>WordPress的3.0.4
修复了一个严重的<a class="reference external" href="http://cn.wordpress.org/2010/12/30/3-0-4-update/">安全漏洞</a>,所以赶紧着手升级飞龙札记的WordPress版本,在管理后台的“更新”页面点击“自动升级”很快就完成了自动更新,系统已成功升级到了3.04。</p>
<p>但是,同样的等我跑去升级<a class="reference external" href="http://17weiguan.com">围观网</a>的时候,却要求我输入FTP信息(主机、用户名、密码等),什么原因造成两者升级的不同呢?</p>
<ol class="arabic simple">
<li>飞龙札记和围观网是运行在两台不同的服务器上,但都是用nginx
proxy到后台的PHP
fastcgi进程进行处理的,服务器的配置基本一致,而两个网站用的WordPress文件是一样的,所以首先就可以排除WordPress版本和服务器配置的差异引起的不同。</li>
<li>两个网站的差别主要体现在主题和插件,这些虽然牵涉到WordPress的设置但是跟WordPress本身及插件升级根本没关系,所以也基本可以排除由WordPres设置差异造成两者升级差异的可能性。</li>
<li>而要求输入FTP信息,目的其实是为了下载WordPress升级文件。两个站一个可以自己下,另一个则要提供FTP账户信息,由此看来应该是文件夹权限问题造成的,仔细对比了一下飞龙札记和围观网的代码文件夹权限,发现飞龙札记的代码文件夹所有者和fastcgi进程的用户是同一个,而围观网的则是两个不同的用户。将围观网的代码文件夹所有者改成fastcgi的进程用户(sudo
chown -R fastcgi-username
/home/local/weiguan),问题解决,围观网自动升级不再需要输入FTP信息了,WordPress瞬间自动升级完毕,大功告成,哈哈!!同理,若你的后台是Apache,则让文件夹用户和Apache进程用户保持一致即可。</li>
</ol>
<p>升级WordPress插件这一问题同理,赶快一键自动升级你的WordPress到3.0.4 吧。</p>
<div id="_mcePaste"
style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;"></p><p class="r rubric" id="wordpress3-0-4"><a class="reference external" href="http://geekfiles.altervista.org/zh/wordpress-3-0-4-risolve-un-grave-bug-di-sicurezza/">*WordPress*的*3.0.4*
修复了一个严重的*安全漏洞*</a></p>
<p></div>让你的Kindle成为离线阅读利器2010-12-31T13:09:00+08:002010-12-31T13:09:00+08:00飞龙tag:feilong.me,2010-12-31:/2010/12/enjoy-read-feeds-in-kindle.html<p>Kindle用来看书很爽,这个无需多说大家都知道,但是用Kindle来看订阅的新闻、博客,当离线的Google
Reader来用,这个估计知道的人并不多,我这就给大家介绍一个网站,让你轻松实现这一功能,在Kindle上尽情的享受离线阅读订阅内容的快乐吧!</p>
<p>我现在几乎所有的RSS订阅都是在每天上下班的路上(无WIFI、3G的情况下)用Kindle3来看的,基本脱离Google
Reader的怀抱。</p>
<ol class="arabic simple">
<li>在亚马逊上也是可以订阅Feeds的,不过那是要钱的,略过不谈。</li>
<li><a class="reference external" href="http://www.kindlefeeder.com">http://www.kindlefeeder.com</a>
这个是老外的网站,可以订阅Feeds发到你的Kindle上,但是定时发送是要收钱的,再略过。</li>
<li><a class="reference external" href="http://dogear.mobi/">http://dogear.mobi/</a>
要重点介绍的是这个,国人做的。其实在我发现这个网站以前,我是想自己做一个这样的网站的,域名都买好了叫feedkindle.com,不过dogear已经很成熟了,我就不用再去择腾了。dogear可以自订阅多个Feed源,然后在管理页面去设置一个时间,让dogear每天定时将订阅内容发送到你的Kindle上,只要每天在定时发送的这个时间后开一次Kindle的WIFI(对于3G版的,因为流量亚马逊要收费,请慎重)就OK了,注意<strong>添加一下@dogear.mobi这个email地址到你Kindle受信任的邮件表里 …</strong></li></ol><p>Kindle用来看书很爽,这个无需多说大家都知道,但是用Kindle来看订阅的新闻、博客,当离线的Google
Reader来用,这个估计知道的人并不多,我这就给大家介绍一个网站,让你轻松实现这一功能,在Kindle上尽情的享受离线阅读订阅内容的快乐吧!</p>
<p>我现在几乎所有的RSS订阅都是在每天上下班的路上(无WIFI、3G的情况下)用Kindle3来看的,基本脱离Google
Reader的怀抱。</p>
<ol class="arabic simple">
<li>在亚马逊上也是可以订阅Feeds的,不过那是要钱的,略过不谈。</li>
<li><a class="reference external" href="http://www.kindlefeeder.com">http://www.kindlefeeder.com</a>
这个是老外的网站,可以订阅Feeds发到你的Kindle上,但是定时发送是要收钱的,再略过。</li>
<li><a class="reference external" href="http://dogear.mobi/">http://dogear.mobi/</a>
要重点介绍的是这个,国人做的。其实在我发现这个网站以前,我是想自己做一个这样的网站的,域名都买好了叫feedkindle.com,不过dogear已经很成熟了,我就不用再去择腾了。dogear可以自订阅多个Feed源,然后在管理页面去设置一个时间,让dogear每天定时将订阅内容发送到你的Kindle上,只要每天在定时发送的这个时间后开一次Kindle的WIFI(对于3G版的,因为流量亚马逊要收费,请慎重)就OK了,注意<strong>添加一下@dogear.mobi这个email地址到你Kindle受信任的邮件表里</strong>即可,dogear网站上也有说明。另外定时发来的是不带图的版本,适合订阅以文字为主的Feed,带图的则要上dogear手动下载。</li>
</ol>
<p>BTW:
dogear开源了部分较核心的功能,开源项目分别见<a class="reference external" href="http://code.google.com/p/feed2mobi/">http://code.google.com/p/feed2mobi/</a>
和<a class="reference external" href="https://bitbucket.org/jiedan/kindlereader">https://bitbucket.org/jiedan/kindlereader</a></p>
<p>转载请注明出处:<a class="reference external" href="http://feilong.me/2010/12/enjoy-read-feeds-in-kindle">http://feilong.me/2010/12/enjoy-read-feeds-in-kindle</a></p>
历数Google Buzz八宗罪2010-12-31T12:14:00+08:002010-12-31T12:14:00+08:00飞龙tag:feilong.me,2010-12-31:/2010/12/google-buzz-top-8-defects.html<p>Buzz在2010各大网站、机构评出的失败的产品列表中均排名前列,原因很简单,Buzz从2月推出至今一直问题不断,特别是开始的隐私泄漏问题和最近的掉评论问题,让很多用户无法忍受,虽然我是Buzz的忠忠忠忠忠实粉丝,但骂你一顿是必须的,恨Buzz你不是李刚啊!下面历数一下Buzz推出以来大大小小、莫名其妙、让人头疼的八宗罪(七宗罪再加一等,最后一等就是这掉评论了)。</p>
<p><img alt="image0" class="size-full wp-image-211 aligncenter" src="/static/2010/12/googlebuzz.jpg" style="width: 460px; height: 250px;" /></p>
<ol class="arabic simple">
<li><strong>隐私泄漏</strong>问题,Buzz刚推出时最为人诟病的就是隐私泄漏问题,如泄漏邮件地址和常联系的人的信息。</li>
<li><strong>掉fo问题</strong>,不用多说,掉fo的同学应该深有体会。</li>
<li><strong>关联恶魔</strong>,Buzz的这个功能很强大,但是被用户滥用了,被人关联刷屏的感觉相信很多人体验过,在Mute功能没出来之前,关联了GR和Twitter的同学们几乎是过街老鼠人人喊打。</li>
<li>掉帖子问题,如果你的账号之前没有绑定手机,而这时你已经开始使用Buzz了,后面哪次登录Buzz时Google要你加入手机信息,而你一旦你绑定手机后,对不起,Buzz当你是一个新号,以前所有的帖子在Buzz里都找不到了,只有你的邮件里会留点残骸。深恶而痛绝之,我的飞龙里至今fo了两个一模一样的五花马。</li>
<li>转帖问题,Buzz转帖尊重原帖,这是对的,但却不尊重中间转的人,再转的人的帖子里只有原帖和原作者信息,没有中间转的那位的一点信息,中转的那位的再创作也就没了。举例,A发原帖,B转A的贴,C转B转A的贴,C转的贴里根本跟没B什么事 …</li></ol><p>Buzz在2010各大网站、机构评出的失败的产品列表中均排名前列,原因很简单,Buzz从2月推出至今一直问题不断,特别是开始的隐私泄漏问题和最近的掉评论问题,让很多用户无法忍受,虽然我是Buzz的忠忠忠忠忠实粉丝,但骂你一顿是必须的,恨Buzz你不是李刚啊!下面历数一下Buzz推出以来大大小小、莫名其妙、让人头疼的八宗罪(七宗罪再加一等,最后一等就是这掉评论了)。</p>
<p><img alt="image0" class="size-full wp-image-211 aligncenter" src="/static/2010/12/googlebuzz.jpg" style="width: 460px; height: 250px;" /></p>
<ol class="arabic simple">
<li><strong>隐私泄漏</strong>问题,Buzz刚推出时最为人诟病的就是隐私泄漏问题,如泄漏邮件地址和常联系的人的信息。</li>
<li><strong>掉fo问题</strong>,不用多说,掉fo的同学应该深有体会。</li>
<li><strong>关联恶魔</strong>,Buzz的这个功能很强大,但是被用户滥用了,被人关联刷屏的感觉相信很多人体验过,在Mute功能没出来之前,关联了GR和Twitter的同学们几乎是过街老鼠人人喊打。</li>
<li>掉帖子问题,如果你的账号之前没有绑定手机,而这时你已经开始使用Buzz了,后面哪次登录Buzz时Google要你加入手机信息,而你一旦你绑定手机后,对不起,Buzz当你是一个新号,以前所有的帖子在Buzz里都找不到了,只有你的邮件里会留点残骸。深恶而痛绝之,我的飞龙里至今fo了两个一模一样的五花马。</li>
<li>转帖问题,Buzz转帖尊重原帖,这是对的,但却不尊重中间转的人,再转的人的帖子里只有原帖和原作者信息,没有中间转的那位的一点信息,中转的那位的再创作也就没了。举例,A发原帖,B转A的贴,C转B转A的贴,C转的贴里根本跟没B什么事。</li>
<li>Like无用,虽然Buzz有Like的功能,但几乎是没用的,因为在Buzz里你根本就看不多一个热贴排行、Like排行之类的东西,热点用户之类的东西也是没有的,开始玩buzz的时候压根就不知道去fo谁,所以民间有些人整理出一些话痨的帖子很受欢迎,不过我解决这个问题的方法比较简单,跟梨叔一样,见人就fo,开始一口气就加了1万。</li>
<li>无法fo人的问题,遇到这个问题的人可能不多,可能在fo的人比较多的情况下会有这个问题,至少我的五花马是怎么也加不了飞龙,虽然我后来unfo了很多人,但还是不行。</li>
<li><strong>狂掉评论</strong>问题,虽然可以捞回来,但是实在太麻烦了,不在你的GTalk好友里的都得常去捞。对于回帖较多的,捞回帖就得把你累死。若为了避免掉评论都加GTalk吧,这又报隐私隐患了不是,特别是fo比较多的人,不能这样玩,这是饮鸩止渴。</li>
</ol>
<p>以上是我自己使用Buzz以来的遇到的问题总结,欢迎大家讨论、补充。骂归骂,目的其实只有一个,就是希望Buzz越做越好。</p>
<p>附图:如何捞回评论,感谢屁民同学提供图片<a class="reference external" href="http://goo.gl/UN9M4">http://goo.gl/UN9M4</a></p>
<p><img alt="image1" class="size-medium wp-image-80 aligncenter" src="/static/2010/12/laohuibuzz-300x217.png" style="width: 300px; height: 217px;" /></p>
当飞龙遭遇python-cn邮件群组2010-12-27T23:51:00+08:002010-12-27T23:51:00+08:00飞龙tag:feilong.me,2010-12-27:/2010/12/felinx-rejected-by-python-cn.html<p>今日下班前,我再一次翻墙去申请加入<a class="reference external" href="http://groups.google.com/group/python-cn">http://groups.google.com/group/python-cn</a>即CPyUG华蟒用户组,等回到家打开邮箱时发现又一次被拒了,管理员效率还真是高啊!我已不记得这是我第几次申请被拒了,估计不小于5次了。这次我为了壮壮胆气,在申请的备注里还把我的python开源网站<a class="reference external" href="http://poweredsites.org">http://poweredsites.org</a>给抬了出来,仍然是不管用啊。</p>
<p>为什么我一直会被拒呢?我是百思不得其解,之前申请的时候我有备注过Python爱好者,或Pythoneer,先不说我的Python水平到底如何,至少我也是一位狂热的Python爱好者,就冲我多次申请这群组的权限这热情,管理员也该批了。</p>
<p>我不知道有多少想加入python-cn的人被拒了,有多少人受过python-cn管理员的打击。我想有些可能刚对python有点兴趣的人,被这一拒说不定对python的热情就大减了,毕竟这是一个较有影响力的中文python群组,这不应是python-cn对python爱好者的态度。</p>
<p>我加入了很多国外的python群组,特别tornado的群组我是经常会说点话的,除了python-cn我还没见过哪个群组是要审批的,更别提申请被拒了。我不知道python-cn的管理员把这个群组搞得这么封闭是为了什么?可能这样一定程度上能防止一些不良人士跑去发垃圾邮件,但这个同时也阻碍了很多对python有兴趣的同学加入,这个得与失应该好好把握。另外像国外的django-user是开放的,里面的用户也很多,我也没看到有多少垃圾邮件在里面横行,即使有垃圾邮件,用户也会让它自动沉淀下去的,python-cn何必搞得这么闭塞?python是open的,python-cn却是close的 …</p><p>今日下班前,我再一次翻墙去申请加入<a class="reference external" href="http://groups.google.com/group/python-cn">http://groups.google.com/group/python-cn</a>即CPyUG华蟒用户组,等回到家打开邮箱时发现又一次被拒了,管理员效率还真是高啊!我已不记得这是我第几次申请被拒了,估计不小于5次了。这次我为了壮壮胆气,在申请的备注里还把我的python开源网站<a class="reference external" href="http://poweredsites.org">http://poweredsites.org</a>给抬了出来,仍然是不管用啊。</p>
<p>为什么我一直会被拒呢?我是百思不得其解,之前申请的时候我有备注过Python爱好者,或Pythoneer,先不说我的Python水平到底如何,至少我也是一位狂热的Python爱好者,就冲我多次申请这群组的权限这热情,管理员也该批了。</p>
<p>我不知道有多少想加入python-cn的人被拒了,有多少人受过python-cn管理员的打击。我想有些可能刚对python有点兴趣的人,被这一拒说不定对python的热情就大减了,毕竟这是一个较有影响力的中文python群组,这不应是python-cn对python爱好者的态度。</p>
<p>我加入了很多国外的python群组,特别tornado的群组我是经常会说点话的,除了python-cn我还没见过哪个群组是要审批的,更别提申请被拒了。我不知道python-cn的管理员把这个群组搞得这么封闭是为了什么?可能这样一定程度上能防止一些不良人士跑去发垃圾邮件,但这个同时也阻碍了很多对python有兴趣的同学加入,这个得与失应该好好把握。另外像国外的django-user是开放的,里面的用户也很多,我也没看到有多少垃圾邮件在里面横行,即使有垃圾邮件,用户也会让它自动沉淀下去的,python-cn何必搞得这么闭塞?python是open的,python-cn却是close的,真是滑稽。</p>
<p>python-cn你们不够open,你们这样搞只会扼杀国内python用户,阻碍国内python水平的提高,这应该是和python-cn的初衷相违背的。</p>
<p>另外再对比一下国外的Quora(虽然不大有可比性,但open的姿态是可比的),多少大牛泡在里头给无名小卒回答问题,我在里面发贴问问题,帖子有点语法错误都有人帮忙修改掉。看看人家Quora,再看看python-cn,我替python-cn感到害羞。</p>
<p>牢骚归牢骚,我还是希望python-cn这个群组能够更好的帮助中国的pythoneer学习、交流python,以一个更加open的姿态。</p>
打造完美博客,WordPress插件推荐2010-12-27T16:28:00+08:002010-12-27T16:28:00+08:00飞龙tag:feilong.me,2010-12-27:/2010/12/recommended-wordpress-plugins.html<p>拜<a class="reference external" href="http://netwiser.blogspot.com/">James</a>所托,今年给洋人写一个小的商用插件<a class="reference external" href="http://www.marketet.com/romi-calculator/">ROMI-Calculator</a>,为此研究了下WordPress,之后趁热打铁用WordPress搭建了<a class="reference external" href="http://17weiguan.com">围观网</a>,期间围观网经过两次改版,前后这么一择腾,可以说现在对WordPress算是小有了解了。</p>
<p>WordPress是一款强大的博客平台,即使你不懂PHP、CSS、JavaScript,甚至连基本的HTML也一无所知,通过WordPress,只要挑选一个自己喜欢的主题再加上一帮插件,你就可以打造一个完美的属于自己的博客网站。</p>
<p>不过,到目前为止WordPress网站上就有<strong>12,455</strong>插件,民间的更是不计其数,要在这成千上万的插件中找到强大实用的插件是件比较困难的事情,特别是对于刚接触WordPress的同学来说,更是头疼。</p>
<p>我也是花了大量时间摸索这么头疼过来的,为了让后来人不再头疼,我这里分享一下我的经验,推荐一些“标配”的WordPress插件。若你发现这里介绍的某个插件的功能在你选择的主题里已经提供了且非常强大,你大可忽略这个插件,一些主题总是会根据自己的需要定制一些功能的。</p>
<p>在说所有的插件之前,先说一下<a class="reference external" href="http://akismet.com/">**Akismet**</a>,Akismet可以说是必装的,Akismet是WordPress标配的的反垃圾留言插件,没有这个你的博客可能会被垃圾留言所淹没,Akismet总的来说效果不错,虽然有时候会有误判和漏判,但大多数情况下可以帮你拦截掉垃圾留言和评论,对于个别误判或漏判的手动处理一下就可以了。使用前需要先申请一个Akismet的API
Key才行,到WordPress …</p><p>拜<a class="reference external" href="http://netwiser.blogspot.com/">James</a>所托,今年给洋人写一个小的商用插件<a class="reference external" href="http://www.marketet.com/romi-calculator/">ROMI-Calculator</a>,为此研究了下WordPress,之后趁热打铁用WordPress搭建了<a class="reference external" href="http://17weiguan.com">围观网</a>,期间围观网经过两次改版,前后这么一择腾,可以说现在对WordPress算是小有了解了。</p>
<p>WordPress是一款强大的博客平台,即使你不懂PHP、CSS、JavaScript,甚至连基本的HTML也一无所知,通过WordPress,只要挑选一个自己喜欢的主题再加上一帮插件,你就可以打造一个完美的属于自己的博客网站。</p>
<p>不过,到目前为止WordPress网站上就有<strong>12,455</strong>插件,民间的更是不计其数,要在这成千上万的插件中找到强大实用的插件是件比较困难的事情,特别是对于刚接触WordPress的同学来说,更是头疼。</p>
<p>我也是花了大量时间摸索这么头疼过来的,为了让后来人不再头疼,我这里分享一下我的经验,推荐一些“标配”的WordPress插件。若你发现这里介绍的某个插件的功能在你选择的主题里已经提供了且非常强大,你大可忽略这个插件,一些主题总是会根据自己的需要定制一些功能的。</p>
<p>在说所有的插件之前,先说一下<a class="reference external" href="http://akismet.com/">**Akismet**</a>,Akismet可以说是必装的,Akismet是WordPress标配的的反垃圾留言插件,没有这个你的博客可能会被垃圾留言所淹没,Akismet总的来说效果不错,虽然有时候会有误判和漏判,但大多数情况下可以帮你拦截掉垃圾留言和评论,对于个别误判或漏判的手动处理一下就可以了。使用前需要先申请一个Akismet的API
Key才行,到WordPress.Com注册一个账号就有了。James同学开始没装Akismet就吃了苦头:)</p>
<p><strong>文章、评论类</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://mitcho.com/code/yarpp/">关联文章 -
YARPP</a>,你在一些网站的上可能有看到过“相关阅读”、“你可能还喜欢”这样的功能,YARPP要做的就是这个,它可以根据文章的标题、分类、标签等信息来帮你找到跟其相关联的其它文章并列举出来,因为列出来的文章是有相关性的,它能够帮你提高网站的Pages/Visit。另外YARPP对网站的feeds也有效,不过要输出全文的feeds才管用。</li>
<li><a class="reference external" href="http://blog.jodies.de/2004/11/recent-comments/">最新评论 - Get Recent
Comments</a>,
WordPress默认的最新评论比较难看不能列出评论内容(有些主题会定制强化这个功能,这里不讨论),而这个插件可以定制最新评论的显示方式,比如我采用的是
<li>%gravatar %comment_author: <a href="%comment_link"
title="%post_title">%comment_excerpt</a></li> 这个格式</li>
<li><a class="reference external" href="http://lesterchan.net/portfolio/programming/php/">访问统计 -
WP-PostViews</a>,
WP-PostViews是一个文章计数统计插件,可以在文章中显示浏览数,还提供了一些统计功能,比如一定时间内浏览最多的文章,你所看到的用WordPress做的网站上提供日排行、周排行、月排行、总排行之类的功能都是居于这个插件来做的。类似的有另外一个插件叫<a class="reference external" href="http://ajaydsouza.com/wordpress/plugins/top-10/">Top
10</a>。</li>
<li>社会化分享,如果是针对国外用户的网站,这个首选的当然是<a class="reference external" href="http://wordpress.org/extend/plugins/sociable/">Sociable</a>,另外要支持Buzz的分享需要装另外一个插件<a class="reference external" href="http://wordpress.org/extend/plugins/google-buzz-for-sociable/">Google
Buzz for
Sociable</a>。但是Sociable对中文社区的支持不够好,比如新浪微博等。明河共影的<a class="reference external" href="http://www.36ria.com/2217">wp-share-list</a>对中文社区的支持非常给力,基本主流的都支持,另外这个不向bShare之类需要依赖于第三方网站,最后一点这个插件还非常酷。飞龙札记文章最下面的分享功能用的就是wp-share-list这个插件。</li>
<li><a class="reference external" href="http://www.romantika.name/v2/2007/05/02/wordpress-plugin-random-posts-widget/">随机文章 - Random Posts
widget</a>,
这个不用过多解释,就是帮你生成随机的文章列表。</li>
<li><a class="reference external" href="http://www.joedolson.com/articles/wp-to-twitter/">同步到Twitter - WP to
Twitter</a>,
将你的博客日志同步至你的Twitter上,这个需要在twitter上为你的博客注册一个APP,另外这个最好跟缩短网址结合使用,可以用bit.ly的API来缩短网站,去bit.ly注册个账号就有API
Key了。</li>
<li>文章打分、置顶,<a class="reference external" href="http://wordpress.org/extend/plugins/wp-postratings/">WP-PostRatings</a>可以给文章按星级打分,在文章页面或首页都可以,功能比较强大,若只想要简单的顶或踩,<a class="reference external" href="http://wordpress.org/extend/plugins/vote-it-up/">Vote
it
up</a>就够了,具体看你自己的需求了。</li>
<li>页面导航(翻页),一般主题都会带页面导航功能的,如果不能让你满意的话,就上<a class="reference external" href="http://wordpress.org/extend/plugins/wp-pagenavi/">WP-PageNavi</a>吧,一般主题也都会推荐你用这个插件的。</li>
<li>联系页面,<a class="reference external" href="http://contactform7.com/">Contact Form
7</a>,帮你做一个联系XX页面的,不用多解释,看一下<a class="reference external" href="http://feilong.me/contact">联系飞龙</a>就明白了。另外这个也可以用来做其它用途,比如投稿页面。</li>
<li>标签云,标签云的插件非常多,这里介绍一个非常酷的用Flash做的标签云插件<a class="reference external" href="http://wordpress.org/extend/plugins/wp-cumulus/">WP-Cumulus</a>,标签云生成后看起来象一个3D的球,你在上面移动鼠标时,这个球会跟着转,就像玩地球仪一样,挺吸引眼球的。不过原生的WP-Cumulus是不支持中文的,你可以搜索下支持中文版的替换默认的这个文件就可以完美支持中文了,下面这张图是围观网上的例子。</li>
</ul>
<p><img alt="image2" class="alignnone size-full wp-image-44" src="/static/2010/12/wptagcloud.jpg" style="width: 268px; height: 281px;" /></p>
<p><strong>SEO类</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://www.arnebrachhold.de/redir/sitemap-home/">Google XML
Sitemaps</a>
它可以帮你自动生成XML格式的网站地图(Sitemaps)文件,并且会并将文件路径加到robots.txt文件中去,有利于Google的搜索收录,当然你也可以登录到<a class="reference external" href="http://www.google.com/webmasters/tools/">Google
Webmasters</a>中手动提交生成的网站地图地址。</li>
<li><a class="reference external" href="http://wordpress.org/extend/plugins/all-in-one-seo-pack/">All in One SEO
Pack</a>
一般WordPress主题都会提供对SEO的支持,但各主题对SEO支持的好坏良莠不齐。使用All
in One SEO
Pack可以在不修改模板的情况下对WordPress进行SEO搜索引擎优化,定义关键字、页面摘要等信息的生成规则,还可以给每篇页面添加独立的关键词和摘要,加速和优化Google等搜索引擎的索引。注意这个插件不要使用过当,如:优化过当造成过多的关键字堆积,这样可能会被搜索引擎当作作弊而给予降权惩罚。</li>
</ul>
<p><strong>广告&流量统计类</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://www.mywordpressplugin.com/adsense-integrator">AdSense
Integrator</a>
广告插件我试了好多个,这个是比较让我满意的,它有一个比较形象的设置界面,让你选择你的广告所在的位置,因为插入的广告其实就是一段HTML代码,你甚至也可以拿它当别的用:)。</li>
<li><a class="reference external" href="http://wordpress.org/extend/plugins/google-analytics-for-wordpress/">Google Analytics for
WordPress</a>,它可以让你不用手动修改模板文件就可以添加Google
Analytics的代码到页面中去。</li>
</ul>
<p><strong>性能优化类</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://ocaoimh.ie/wp-super-cache/">WP Super
Cache</a>,将页面静态化缓存下来,它可以大大降低网站的数据库查询操作,节省系统资源,提高访问速度,结合mod_rewrite来用的话性能更佳。如果你的网站页面很多这个是必装的了。它还提供了一个preload的功能,可以帮你主动的预先生成一些页面的缓存。</li>
<li>页面压缩,压缩页面多余的空格和换行和注释,<a class="reference external" href="http://www.mandar-marathe.com/wp-compress-html">WP-Compress-HTML</a>或<a class="reference external" href="http://www.svachon.com/wp-html-compression/">WP-HTML-Compression</a>都可以实现这个功能,不过这里面有一点小道道,不能把所有的换行都压缩掉,不然写在CDATA里的Javascripts脚本可能不管用了。</li>
<li><a class="reference external" href="http://wordpress.org/extend/plugins/wp-gravatar-mini-cache/">WP Gravatar Mini
Cache</a>,缓存Gravatar的头像文件,能否优化性能是个问号。其实它的最大用处是解决Gravatar头像不能正常显示的问题的(拜GFW所赐,现在Gravatar的大头像网站是被墙了的)。不过这个要求你的服务器在国外,若服务器在国内这个插件无效。</li>
</ul>
<p><strong>网站后台类</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://austinmatzko.com/wordpress-plugins/wp-db-backup/">WordPress Database
Backup</a>,备份博客数据库数据到本地或服务器,也可以设定定时任务发送备份数据文件到你的邮箱。</li>
<li><a class="reference external" href="http://www.viper007bond.com/wordpress-plugins/regenerate-thumbnails/">Regenerate
Thumbnails</a>,可以帮你重新生成上传图片的特色图片文件,如果你修改过上传图片大小的设置的话。</li>
<li>邮件后台,<a class="reference external" href="http://wordpress.org/extend/plugins/wp-mail-smtp/">WP-Mail-SMTP</a>可以自定义博客后台邮件地址,让你用SMTP服务器发送系统邮件。而<a class="reference external" href="http://wordpress.org/extend/plugins/new-user-email-set-up/">New
User Email
Setup</a>是用来自定义注册、找回密码等系统邮件内容的。</li>
</ul>
<p>希望上面的这些插件介绍能够对你有所帮助,助你打造一个属于自己的完美的WordPress博客。这里介绍的插件我都用过,如果有任何问题或疑问可以直接回帖或<a class="reference external" href="http://feilong.me/pages/contact">联系飞龙</a>。</p>
博客开张2010-12-26T00:00:00+08:002010-12-26T00:00:00+08:00飞龙tag:feilong.me,2010-12-26:/2010/12/start-blogging.html<p>很早就有弄个博客的念头,可一直未能成行,理由很多但都不能当合理的借口。</p>
<p>算来网站已做了好几个,博客却一直寄人篱下,说来就觉得心酸,特别是那个什么Javaeye,我都被气死好几回了,再也不去了。</p>
<p>好了,最近为了开发了一个小的插件赚了点零花钱,花了些时间研究Wordpress,顺带弄了个<a class="reference external" href="http://17weiguan.com/">围观网</a>,现在干脆乘热打铁再弄一个自己的博客。</p>
<p>虽然现在微博横行,为什么还是要开博了,我觉得主要有几点:</p>
<ol class="arabic simple">
<li>首先,博客还是要的,好记性不如烂笔头,偏偏我记性还不好,这就更需要有个地方来把一些有意义的东西给记录下来。比如平时工作、开发网站中碰到的
疑难的问题,最后辛辛苦苦才搞定的解决方案,这些知识积累除了自己可能后面还会用到外,另外也可以帮助碰到同样问题的同学,何乐而不博呢?</li>
<li>别的站都是虚的,自己的博客还是最方便,特别是历史纪录查询。比如贴在twitter、buzz或新浪微博的东西想查自己的东西的时候不是那么容易。</li>
<li>将来时间长了翻回来看,博客的历史会是自己工作、人生的一大注解。</li>
<li>一个独立的博客也是一个比较好的交友平台,能够结识志同道合的朋友。</li>
</ol>
<p>所以还等什么,准备开始写博客吧...</p>
<p>很早就有弄个博客的念头,可一直未能成行,理由很多但都不能当合理的借口。</p>
<p>算来网站已做了好几个,博客却一直寄人篱下,说来就觉得心酸,特别是那个什么Javaeye,我都被气死好几回了,再也不去了。</p>
<p>好了,最近为了开发了一个小的插件赚了点零花钱,花了些时间研究Wordpress,顺带弄了个<a class="reference external" href="http://17weiguan.com/">围观网</a>,现在干脆乘热打铁再弄一个自己的博客。</p>
<p>虽然现在微博横行,为什么还是要开博了,我觉得主要有几点:</p>
<ol class="arabic simple">
<li>首先,博客还是要的,好记性不如烂笔头,偏偏我记性还不好,这就更需要有个地方来把一些有意义的东西给记录下来。比如平时工作、开发网站中碰到的
疑难的问题,最后辛辛苦苦才搞定的解决方案,这些知识积累除了自己可能后面还会用到外,另外也可以帮助碰到同样问题的同学,何乐而不博呢?</li>
<li>别的站都是虚的,自己的博客还是最方便,特别是历史纪录查询。比如贴在twitter、buzz或新浪微博的东西想查自己的东西的时候不是那么容易。</li>
<li>将来时间长了翻回来看,博客的历史会是自己工作、人生的一大注解。</li>
<li>一个独立的博客也是一个比较好的交友平台,能够结识志同道合的朋友。</li>
</ol>
<p>所以还等什么,准备开始写博客吧...</p>