<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><fs:self_link href="http://feed.feedsky.com/lenciel" type="application/rss+xml" /><lastBuildDate>Mon, 28 May 2012 02:46:49 GMT</lastBuildDate><title>俏也不争春，只把春来叫</title><description>lenciel's weblog</description><image><url>http://www.feedsky.com/feed/lenciel/sc/gif</url><title>俏也不争春，只把春来叫</title><link>http://lenciel.cn</link></image><link>http://lenciel.cn</link><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><language>en</language><pubDate>Mon, 28 May 2012 02:59:06 GMT</pubDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/lenciel" /><feedburner:info uri="lenciel" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Python上手指南</title><link>http://feedproxy.google.com/~r/lenciel/~3/DsUG4tFPIZo/</link><content:encoded>&lt;p&gt;刚刚开始使用Python开发的新手，遇到的第一个瓶颈（常常）就是缺乏对整个Python生态系统的理解。大家总是在网上搜索完成这件事或者那件事的“标准做法”，就像我们使用其他编程语言的时候常常需要掌握的一样。&lt;/p&gt;
&lt;p&gt;在和几个朋友开始iDVR的开发的时候，我们在内部Wiki上维护过一个Python中常见问题列表。我们的目标是随着项目的不断进步，这个内部的wiki能够变成一个豪华的Q&amp;amp;A索引，但是事实证明项目一忙起来就没有人去写Wiki了。&lt;/p&gt;
&lt;p&gt;最近陆续有朋友问一些Python相关的问题，想想其实要用三言两语说清楚并不容易，就决定在那份wiki的基础上自己写一个版本，给那些刚开始使用Python（从来没有编过程的读起来可能没啥帮助）的同学。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Python编程是个大话题，不是这里讨论的内容。如果你没有太多编程经验，应该先去看一点儿Python的&lt;a href="http://learnpythonthehardway.org/" target="_blank"&gt;入门书籍&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;另外，这片文章是基于Windows（最好是Win7 32bit）操作系统。潮人请不要问为啥不是Mac或者Linux，因为本座主要用的机器（包括码这篇Blog）都是用Win7 32bit。不过除开环境搭建，这里提到的大部分概念对其他系统都是适用的。&lt;/p&gt;
&lt;p&gt;如果你有环境搭建上的问题，最靠谱的提问的地方不是CSDN或者百度知道，是&lt;a href="http://stackoverflow.com/" target="_blank"&gt;Stack Overflow&lt;/a&gt;。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;版本选择&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;本座在某软件公司面试的时候别人看到简历上有Python就问，Python3用过吗？本座老实回答没有，结果面试官就停下他正在笔记本上google的微操，在脸上流露出一丝嘲讽…&lt;/p&gt;
&lt;p&gt;不过，除了Python这门语言本身的开发者，大多数像本座这种使用Python的人，都没有紧跟Python3的步伐。Python3（或者叫Py3K）是一个大多数我熟悉的包，框架和工具都还没有完备支持的版本（在未来的数年本座也看不到希望）。如果不是想研究Python3的新特性或者具体实现，个人觉得初学的开发者使用2.7.x是最安全的版本（本座还在用进M公司就装好的2.6版本）。&lt;/p&gt;
&lt;p&gt;如果你比较熟悉Python但是不确定该不该升级到Python3，不妨先去观赏一下&lt;a href="http://python3wos.appspot.com/"&gt;Python 3 Wall of Shame&lt;/a&gt; (墙外，你们懂的)。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;VM选择&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Python是&lt;a href="http://zh.wikipedia.org/zh-hk/%E8%84%9A%E6%9C%AC%E8%AF%AD%E8%A8%80" target="_blank"&gt;脚本语言&lt;/a&gt;，因此需要VM。CPython是最主流的选择，也被当成其他VM实现时的参考。其他常见的还有用Python实现的&lt;a href="http://pypy.org/"&gt;PyPy&lt;/a&gt;，用Java实现的&lt;a href="http://www.jython.org/"&gt;Jython&lt;/a&gt; 以及用Microsoft .Net CLR实现的&lt;a href="http://ironpython.net/"&gt;IronPython&lt;/a&gt;。如果你不是非常非常确定你自己要选用别的，就安装CPython吧。&lt;/p&gt;
&lt;p&gt;换句话说，前面这堆关于VM和版本选择的建议在你看来不知所云，你需要的就是&lt;a href="http://www.python.org/getit/" target="_blank"&gt;CPython 2.7.x版本&lt;/a&gt;。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Python安装&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;下载之后的.exe安装文件安装的时候有一个地方需要注意：如果你是在Vista/Win7这样的C盘权限控制异常严格的操作系统，最好用右键“Run as administrator”。这点也适用于你下载到的被其他人编译成exe发布的Python package。嗯，什么是package？&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;理解package&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Python没有一个内置的package管理体系。实际上Python下面一个package是什么也是一个很“不具体”的概念。就像前面提到的，Python下面的代码是以module为单位存在的。每个module既可以是一个只有一个函数的文件，也可以是一个包含了一个或者多个子module的目录。而module和package之间的区别是非常模糊的，每个module都可以被认为是一个package。&lt;/p&gt;
&lt;p&gt;和所有的编程环境一样，在Python下面有一些函数和类是全局可见的（&lt;code&gt;str&lt;/code&gt;，&lt;code&gt;len&lt;/code&gt;，&lt;code&gt;Exception&lt;/code&gt;等等），而另外一些需要通过&lt;code&gt;import&lt;/code&gt;语句导入，比如：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;&lt;span style="color: #66cc66;"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;import &lt;span style="color: #dc143c;"&gt;os&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;from &lt;span style="color: #dc143c;"&gt;os&lt;/span&gt;.&lt;span style="color: yellow;"&gt;path&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;import&lt;/span&gt; basename, dirname&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里&lt;code&gt;import&lt;/code&gt;被调用的时候，Python是从哪里把这些module导入的呢？其实，在你安装Python的时候，module的导入路径已经被自动设置过了。这个过程的具体实现是跟你运行的平台相关的，你可以通过&lt;code&gt;sys.path&lt;/code&gt;来查看被设置的路径究竟是什么。比如本座的是：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;&lt;span style="color: green;"&gt;&amp;#91;&lt;/span&gt;&lt;span style="color: pink;"&gt;''&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;demjson-1.4-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;anyjson-0.2.5-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;pmw-1.3.2-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;paramiko-1.7.6-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;treewidgets-1.0a1-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;mechanize-0.2.3-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;pylint-0.22.0-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;logilab_astng-0.21.0-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;logilab_common-0.53.0-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;unittest2-0.5.1-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;virtualenv-1.5.1-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django_staticfiles-0.3.2-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django_attachments-0.3dev-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django_ajax_validation-0.1.4-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django_email_confirmation-0.2.dev4-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;distribute-0.6.10-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django_timezones-0.2.dev1-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django-1.3-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\ &lt;/span&gt;&lt;span style="color: #000099; font-weight: bold;"&gt;\P&lt;/span&gt;ython26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;rbtools-0.3.2-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;django_debug_toolbar-0.8.4-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;suds-0.4-py2.6.egg'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Windows&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;system32&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;python26.zip'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;DLLs'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;plat-win'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib-tk'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;PIL'&lt;/span&gt;,
&lt;span style="color: pink;"&gt;'C:&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;Python26&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;lib&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;site-packages&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;wx-2.8-msw-unicode'&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;#93;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Python在导入的module的时候，是按照这个列表“自顶向下，见好就收”的方式运作的。也就是说如果你正好机器上有两个路径下面安装了同样名称的module，先被搜索到的那个就会被导入。有的时候，你确信自己受到了这种机制的干扰，也可以通过下面的办法来hack回来：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;&lt;span style="color: #dc143c;"&gt;sys&lt;/span&gt;.&lt;span style="color: yellow;"&gt;path&lt;/span&gt;.&lt;span style="color: yellow;"&gt;insert&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff4500;"&gt;0&lt;/span&gt;, &lt;span style="color: pink;"&gt;'path&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;to&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;your&lt;span style="color: #000099; font-weight: bold;"&gt;\\&lt;/span&gt;packages'&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;进行一段时间的Python开发过后你总是会有很多的包，于是这个办法你会觉得非常的方便。但是，请结合后面的内容默默记住，不到万不得已，不要这样hack。&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;The PYTHONPATH&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;&lt;code&gt;PYTHONPATH&lt;/code&gt;是一个环境变量（可以win+break到高级设置里面去设置），可以简单的理解它就是Windows下面的&lt;code&gt;PATH&lt;/code&gt;变量，不过只是对Python可见而已。在很多Python的教程里面，会说所有你想要让Python搜索module的路径，都应该加到这个变量对应的列表里面。&lt;/p&gt;
&lt;p&gt;其实前面提到过，在Python安装的时候搜索路径已经被自动设置过一次。所以&lt;code&gt;PYTHONPATH&lt;/code&gt;这个变量并不是必须加的。而且，作为开发环境满坑满谷的程序员，我们都喜欢把Path里面搞得干干净净的（比如本座干活都习惯在bat里面先设置相关的路径再起相应的Eclipse）。这种一启动就load一堆的办法，自己喜欢也可以用，但是更推荐后面会说的&lt;code&gt;virtualenv&lt;/code&gt;。&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;第三方package&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;首先，入门之后要开始正经干活，你总是需要安装一些第三方的Package。安装的办法有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;下载别人编译好的Windows的版本exe&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;pip&lt;/code&gt;或者&lt;code&gt;easy_install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自己从代码安装&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;三种办法干的事情都是类似的：下载package的依赖包，编译（需要的话）和拷贝目标文件到一个默认的第三方Package路径。那么，哪里去找安装需要的文件呢？一般来说：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Google&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi"&gt;Python Package Index(or PyPI)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;各种开源的代码库(&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt;/&lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt;/&lt;a href="https://bitbucket.org/"&gt;BitBucket&lt;/a&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;&lt;strong&gt;安装别人编译好的exe&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;注意下载的时候看清别人编译是在32还是64bit的Windows，Python的版本和你用的一致不一致。运行exe的时候注意右键Run as Administrator。就这么简单。&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;使用pip&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;&lt;code&gt;easy_install&lt;/code&gt;已经慢慢失宠了，主要介绍一下它的替代品：&lt;code&gt;pip&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip&lt;/code&gt;是用来安装和管理Python Package的工具。它不是随Python默认安装的，因此需要额外安装。安装完毕之后我们就可以在命令行里面调用它来管理package了。比如你要安装&lt;code&gt;pygame&lt;/code&gt;这个package，只需要：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;pip install pygame&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;而如果你想删除它的话，则运行：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;pip uninstall pygame&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pip&lt;/code&gt;默认会按照你指定的名字，搜索和安装最新的stable版本的包。但我们常常需要安装某个特定版本的包，这个时候需要你在命令行里面指定：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;pip install pygame==version_number&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果你安装的版本不对，可以通过&lt;code&gt;upgrade&lt;/code&gt;命令升级/降级到指定版本：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;pip install pygame==version_number –upgrade&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;由于Python高度依赖开源团体，很多最新的package都没有在PyPI上面，我们常常需要从代码库直接安装package。在&lt;code&gt;pip&lt;/code&gt;下面可以直接&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;$ pip install git+http://somedomain.&lt;span style="color: yellow;"&gt;com&lt;/span&gt;/path/to/git-repo&lt;span style="color: #808080; font-style: italic;"&gt;#egg=packagename&lt;/span&gt;
$ pip install hg+http://somedomain.&lt;span style="color: yellow;"&gt;com&lt;/span&gt;/path/to/hg-repo&lt;span style="color: #808080; font-style: italic;"&gt;#egg=packagename&lt;/span&gt;
$ pip install svn+http://somedomain.&lt;span style="color: yellow;"&gt;com&lt;/span&gt;/path/to/svn-repo&lt;span style="color: #808080; font-style: italic;"&gt;#egg=packagename&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当然，前提是git/hg/svn这些工具你都安装好了并且在命令行里面能够执行。&lt;/p&gt;
&lt;p&gt;上面这些&lt;code&gt;egg&lt;/code&gt;是什么蛋呢？你可以认为它们就是Package源代码和一些metadata打成的压缩包。&lt;code&gt;pip&lt;/code&gt;会读取&lt;code&gt;egg&lt;/code&gt;里面的&lt;code&gt;setup.py&lt;/code&gt;文件，然后安装&lt;code&gt;egg&lt;/code&gt;到你的文件系统。&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;从Python源码安装&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;从源代码安装虽然是最复杂的，但是也没那么复杂。把你下载的源代码解压之后，找到&lt;code&gt;setup.py&lt;/code&gt;所在的路径，然后运行下面的命令：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;python setup.&lt;span style="color: yellow;"&gt;py&lt;/span&gt; install&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;也许你觉得这样也挺容易的，为啥要去用&lt;code&gt;pip&lt;/code&gt;？因为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;省去你上网找源代码，解压，安装这些动作&lt;/li&gt;
&lt;li&gt;更重要的是，&lt;code&gt;pip&lt;/code&gt;不但装，而且管。你可以升级和降级一个Package。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;strong&gt;安装需要编译的package&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;这种一般是因为Package里面有c/cpp的代码。如果你能找到别人编译好的exe文件或者用&lt;code&gt;pip&lt;/code&gt;，最好不要自己折腾。只有非常非常罕见的情况下你需要自己编译，过程中一般来说都会需要用&lt;code&gt;cygwin&lt;/code&gt;之类的东西，在前面几次你可以多看看每个Package的&lt;code&gt;readme&lt;/code&gt;关于编译的说明。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;开发环境&lt;/strong&gt;&lt;/h4&gt;
&lt;h5&gt;&lt;strong&gt;virtualenv&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;&lt;code&gt;virtualenv&lt;/code&gt;无疑是当前Python开发者心中“必知必会”类的工具了。&lt;code&gt;virtualenv&lt;/code&gt;主要就是提供一个“独立的”Python开发环境。为什么需要“独立”的开发环境？在不知道&lt;code&gt;virtualenv&lt;/code&gt;之前Python包满坑满谷的本座自然是有很多槽可以吐，不过最好的答案是&lt;code&gt;virtualenv&lt;/code&gt;的文档里面说的：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The basic problem being addressed is one of dependencies and versions, and indirectly permissions. Imagine you have an application that needs version 1 of LibFoo, but another application requires version 2. How can you use both these applications? If you install everything into /usr/lib/python2.7/site-packages (or whatever your platform&amp;#8217;s standard location is), it&amp;#8217;s easy to end up in a situation where you unintentionally upgrade an application that shouldn&amp;#8217;t be upgraded.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;简单来说，就是每个工程使用自己独立的&lt;code&gt;virtualenv&lt;/code&gt;进行开发，所有该工程需要依赖的Package都安装在这个&lt;code&gt;virutalenv&lt;/code&gt;里面。&lt;code&gt;virutalenv&lt;/code&gt;的安装同样是使用&lt;code&gt;pip&lt;/code&gt;：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;pip install virtualenv&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后就可以建立属于自己项目的开发环境：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;D:\Lenciel\Temp mkdir my_project_env
&amp;nbsp;
D:\Lenciel\Temp\virtualenv --distribute my_project_env
&amp;nbsp;
  New python executable &lt;span style="color: #ff7700;font-weight:bold;"&gt;in&lt;/span&gt; my_project_env\Scripts\python.&lt;span style="color: yellow;"&gt;exe&lt;/span&gt;
  Installing distribute.................&lt;span style="color: yellow;"&gt;done&lt;/span&gt;.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;建立的目录下面会自动的安装好&lt;code&gt;pip&lt;/code&gt;等工具：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="bash" style="font-family:monospace;"&gt;-my_project_env
&lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;-- Scripts &lt;span style="color: #666666; font-style: italic;"&gt;# -- Python解释器的拷贝/pip脚本/activiate脚本/deactivate脚本等&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;-- Lib     &lt;span style="color: #666666; font-style: italic;"&gt;# -- 所有库（包括激活后使用pip安装的库都会放在这里）&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在命令行执行activate脚本就可以激活你新建的环境。环境被激活后，主要通过下面两个功能保持独立完整性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当你在被激活的环境里面使用&lt;code&gt;pip&lt;/code&gt;安装一个Package的时候，它只会被安装在这个工作目录下面&lt;/li&gt;
&lt;li&gt;当你&lt;code&gt;import&lt;/code&gt;的时候，会先从工作目录下面去搜索，然后才会搜索系统目录下的&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;需要注意的是，在系统目录下面安装的包，对所有的&lt;code&gt;virtualenv&lt;/code&gt;建立的环境都是可见的。如果你不想在你建立的&lt;code&gt;virtualenv&lt;/code&gt;里面看到这些包，可以使用&lt;code&gt;--no-site-packages&lt;/code&gt;参数建立开发环境：&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;$ virtualenv my_project_venv --no-site-packages&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4&gt;&lt;strong&gt;其他的工具&lt;/strong&gt;&lt;/h4&gt;
&lt;h5&gt;&lt;strong&gt;编辑器&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;在不同的项目里面本座用过vim/Eclipse+PyDev/PyCharm。现在vim和PyCharm用得比较多一点，PyDev一直有一些诡异的问题。比如那个“&lt;a href="https://www.google.com.hk/search?num=30&amp;amp;hl=en&amp;amp;newwindow=1&amp;amp;c2coff=1&amp;amp;safe=strict&amp;amp;site=&amp;amp;source=hp&amp;amp;q=Unresolved+import+pydev&amp;amp;btnK=Google+Search&amp;amp;qscrl=1" target="_blank"&gt;Unresolved import&lt;/a&gt;”从一开始到现在都好像没有被真正解决过。&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;编码规范&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;&lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP 0008&lt;/a&gt;推荐了非常完整的一套编码规范，目的就是让全世界编写Python脚本的同学们用相同的方式去对齐代码，命名变量、类和函数。每个严肃的Pythoner都应该认真的学习和理解这些规范，并且贯彻执行。&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;Python标准库&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;Python的标准库提供了相当完备的功能。就像Java的工程师需要熟悉系统自带的API文档一样，了解标准库的用法是非常有好处的。另外，这些标准库都是很好的范例，特别是在支持跨平台使用这方面。&lt;/p&gt;
&lt;p&gt;官方文档在&lt;a href="http://docs.python.org/library/" target="_blank"&gt;这里&lt;/a&gt;。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;嗯哼&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;前面列了不少东西，只是希望给新手一个上路指引。Python下面有用的工具，有趣的包很多很多。随着你学习和应用这门语言，不断深入它，你会自己慢慢发觉那些你自己最需要/愿意熟悉的部分。&lt;/p&gt;
&lt;p&gt;Python的另外一大财富就是它的开源社区，条件成熟的时候，你也应该参与到这样的开发活动里面去。&lt;/p&gt;
&lt;p&gt;最后是每个Pythoner都津津乐道的Zen Of Python送给刚开始学习的朋友。&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;&lt;span style="color: #66cc66;"&gt;&amp;amp;&lt;/span&gt;gt&lt;span style="color: #66cc66;"&gt;;&amp;amp;&lt;/span&gt;gt&lt;span style="color: #66cc66;"&gt;;&amp;amp;&lt;/span&gt;gt&lt;span style="color: #66cc66;"&gt;;&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;import this
The Zen of Python, by Tim Peters
&amp;nbsp;
Beautiful &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than ugly.
&lt;span style="color: yellow;"&gt;Explicit&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than implicit.
&lt;span style="color: yellow;"&gt;Simple&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than &lt;span style="color: #008000;"&gt;complex&lt;/span&gt;.
&lt;span style="color: yellow;"&gt;Complex&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than complicated.
&lt;span style="color: yellow;"&gt;Flat&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than nested.
&lt;span style="color: yellow;"&gt;Sparse&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than dense.
&lt;span style="color: yellow;"&gt;Readability&lt;/span&gt; counts.
&lt;span style="color: yellow;"&gt;Special&lt;/span&gt; cases aren&lt;span style="color: pink;"&gt;'t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you'&lt;/span&gt;&lt;span style="color: #dc143c;"&gt;re&lt;/span&gt; Dutch.
&lt;span style="color: yellow;"&gt;Now&lt;/span&gt; &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; better than never.
&lt;span style="color: yellow;"&gt;Although&lt;/span&gt; never &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; often better than &lt;span style="color: #66cc66;"&gt;*&lt;/span&gt;right&lt;span style="color: #66cc66;"&gt;*&lt;/span&gt; now.
&lt;span style="color: yellow;"&gt;If&lt;/span&gt; the implementation &lt;span style="color: #ff7700;font-weight:bold;"&gt;is&lt;/span&gt; hard to explain, it&lt;span style="color: pink;"&gt;'s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let'&lt;/span&gt;s do more of those&lt;span style="color: #66cc66;"&gt;!&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Happy Pythoning…!!&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255121/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/05/get-start-with-python/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/05/get-start-with-python/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>刚刚开始使用Python开发的新手，遇到的第一个瓶颈（常常）就是缺乏对整个Python生态系统的理解。大家总是在网上搜索完成这件事或者那件事的“标准做法”，就像我们使用其他编程语言的时候常常需要掌握的一样。 在和几个朋友开始iDVR的开发的时候，我们在内部Wiki上维护过一个Python中常见问题列表。我们的目标是随着项目的不断进步，这个内部的wiki能够变成一个豪华的Q&amp;#38;A索引，但是事实证明项目一忙起来就没有人去写Wiki了。 最近陆续有朋友问一些Python相关的问题，想想其实要用三言两语说清楚并不容易，就决定在那份wiki的基础上自己写一个版本，给那些刚开始使用Python（从来没有编过程的读起来可能没啥帮助）的同学。 Warning Python编程是个大话题，不是这里讨论的内容。如果你没有太多编程经验，应该先去看一点儿Python的入门书籍。 另外，这片文章是基于Windows（最好是Win7 32bit）操作系统。潮人请不要问为啥不是Mac或者Linux，因为本座主要用的机器（包括码这篇Blog）都是用Win7 32bit。不过除开环境搭建，这里提到的大部分概念对其他系统都是适用的。 如果你有环境搭建上的问题，最靠谱的提问的地方不是CSDN或者百度知道，是Stack Overflow。 版本选择 本座在某软件公司面试的时候别人看到简历上有Python就问，Python3用过吗？本座老实回答没有，结果面试官就停下他正在笔记本上google的微操，在脸上流露出一丝嘲讽… 不过，除了Python这门语言本身的开发者，大多数像本座这种使用Python的人，都没有紧跟Python3的步伐。Python3（或者叫Py3K）是一个大多数我熟悉的包，框架和工具都还没有完备支持的版本（在未来的数年本座也看不到希望）。如果不是想研究Python3的新特性或者具体实现，个人觉得初学的开发者使用2.7.x是最安全的版本（本座还在用进M公司就装好的2.6版本）。 如果你比较熟悉Python但是不确定该不该升级到Python3，不妨先去观赏一下Python 3 Wall of Shame (墙外，你们懂的)。 VM选择 Python是脚本语言，因此需要VM。CPython是最主流的选择，也被当成其他VM实现时的参考。其他常见的还有用Python实现的PyPy，用Java实现的Jython 以及用Microsoft .Net CLR实现的IronPython。如果你不是非常非常确定你自己要选用别的，就安装CPython吧。 换句话说，前面这堆关于VM和版本选择的建议在你看来不知所云，你需要的就是CPython 2.7.x版本。 Python安装 下载之后的.exe安装文件安装的时候有一个地方需要注意：如果你是在Vista/Win7这样的C盘权限控制异常严格的操作系统，最好用右键“Run as administrator”。这点也适用于你下载到的被其他人编译成exe发布的Python package。嗯，什么是package？ 理解package Python没有一个内置的package管理体系。实际上Python下面一个package是什么也是一个很“不具体”的概念。就像前面提到的，Python下面的代码是以module为单位存在的。每个module既可以是一个只有一个函数的文件，也可以是一个包含了一个或者多个子module的目录。而module和package之间的区别是非常模糊的，每个module都可以被认为是一个package。 和所有的编程环境一样，在Python下面有一些函数和类是全局可见的（str，len，Exception等等），而另外一些需要通过import语句导入，比如： &amp;#62;&amp;#62;&amp;#62;import os &amp;#62;&amp;#62;&amp;#62;from os.path import basename, dirname 这里import被调用的时候，Python是从哪里把这些module导入的呢？其实，在你安装Python的时候，module的导入路径已经被自动设置过了。这个过程的具体实现是跟你运行的平台相关的，你可以通过sys.path来查看被设置的路径究竟是什么。比如本座的是： &amp;#91;'', 'C:\\Python26\\lib\\site-packages\\demjson-1.4-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\anyjson-0.2.5-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\pmw-1.3.2-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\paramiko-1.7.6-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\treewidgets-1.0a1-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\mechanize-0.2.3-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\pylint-0.22.0-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\logilab_astng-0.21.0-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\logilab_common-0.53.0-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\unittest2-0.5.1-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\virtualenv-1.5.1-py2.6.egg', 'C:\\Python26\\lib\\site-packages\\django_staticfiles-0.3.2-py2.6.egg', [...]&lt;img src="http://www1.feedsky.com/t1/643255121/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/05/get-start-with-python/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>档案一理</category><category>python</category><pubDate>Mon, 28 May 2012 10:46:49 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/05/get-start-with-python/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=2078</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/05/get-start-with-python/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255121/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/05/get-start-with-python/</feedburner:origLink></item><item><title>幽怨生倦怠</title><link>http://feedproxy.google.com/~r/lenciel/~3/XKVwmRtgRxU/</link><content:encoded>&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2012/03/takeabreak.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="take a break" border="0" alt="take a break" src="http://lenciel.cn/wp-content/uploads/2012/03/takeabreak_thumb.jpg" width="604" height="404" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Google的美女副总&lt;a href="https://plus.google.com/118207880179234484610/posts" target="_blank"&gt;Marissa Mayer&lt;/a&gt;最近做了一个演讲，里面提到了如何避免自己的团队出现“倦怠”。&lt;/p&gt;
&lt;p&gt;简单来说她的理论就是倦怠的根源是幽怨。当工程师需要因为工作而做出牺牲的时候——比如，不能去陪父母过生日，取消和女朋友的约会，错过小孩的演出——总是会在心中产生幽怨的。为了消除这种影响，她会主动和员工沟通，了解他们的习惯：虽然做IT行业，加班是难免的。但是如果你每周三都需要和朋友们踢球才能保持欢乐的情绪，那么星期三永远不能安排你加班。&lt;/p&gt;
&lt;p&gt;这的确是一个很需要注意的现象。即使是在很多产品销量相当不错大家的收入也还可以的公司或者项目组（和那些预算不足，或者需求改动过于频繁，或者呕心沥血但是最终没法盈利的项目比起来这种项目简直是可遇不可求啊），你也会发现有很多人不开心。大多数都是因为在项目研发的过程中，大家拼得太猛。&lt;/p&gt;
&lt;p&gt;对于本座而言，不幽怨似乎比较简单：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每周踢球至少一次&lt;/li&gt;
&lt;li&gt;吃得舒服（有比较清淡的伙食）&lt;/li&gt;
&lt;li&gt;至少有4个晚上回家不用做公司里面的事情可以自己安排&lt;/li&gt;
&lt;li&gt;一年至少有一个礼拜的连续的不用开电脑的假期&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有空也收集一下组里面其他同学的，争取帮大家清清怨气。&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255122/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/03/burnout-is-caused-by-resentment/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/03/burnout-is-caused-by-resentment/feed/</wfw:commentRss><slash:comments>2</slash:comments><description>Google的美女副总Marissa Mayer最近做了一个演讲，里面提到了如何避免自己的团队出现“倦怠”。 简单来说她的理论就是倦怠的根源是幽怨。当工程师需要因为工作而做出牺牲的时候——比如，不能去陪父母过生日，取消和女朋友的约会，错过小孩的演出——总是会在心中产生幽怨的。为了消除这种影响，她会主动和员工沟通，了解他们的习惯：虽然做IT行业，加班是难免的。但是如果你每周三都需要和朋友们踢球才能保持欢乐的情绪，那么星期三永远不能安排你加班。 这的确是一个很需要注意的现象。即使是在很多产品销量相当不错大家的收入也还可以的公司或者项目组（和那些预算不足，或者需求改动过于频繁，或者呕心沥血但是最终没法盈利的项目比起来这种项目简直是可遇不可求啊），你也会发现有很多人不开心。大多数都是因为在项目研发的过程中，大家拼得太猛。 对于本座而言，不幽怨似乎比较简单： 每周踢球至少一次 吃得舒服（有比较清淡的伙食） 至少有4个晚上回家不用做公司里面的事情可以自己安排 一年至少有一个礼拜的连续的不用开电脑的假期 有空也收集一下组里面其他同学的，争取帮大家清清怨气。&lt;img src="http://www1.feedsky.com/t1/643255122/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/03/burnout-is-caused-by-resentment/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>project management</category><category>仰天一笑</category><pubDate>Sat, 31 Mar 2012 18:55:36 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/03/burnout-is-caused-by-resentment/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=2029</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/03/burnout-is-caused-by-resentment/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255122/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/03/burnout-is-caused-by-resentment/</feedburner:origLink></item><item><title>Done List</title><link>http://feedproxy.google.com/~r/lenciel/~3/ModhOHhwxb0/</link><content:encoded>&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2012/03/nerd_sniping.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="nerd_sniping" border="0" alt="nerd_sniping" src="http://lenciel.cn/wp-content/uploads/2012/03/nerd_sniping_thumb.png" width="620" height="320" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;起&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href="http://xkcd.com/730/" target="_blank"&gt;xkcd&lt;/a&gt;一直是本座最喜欢的网站（嗯哼）。上面这幅图说了一个很有趣的现象，正好最近深有体会，就来这边吐槽一下。整个经过是：&lt;/p&gt;
&lt;p&gt;大前天回到家感觉不算太忙，本座就开始家姐布置的家庭作业：做一个用于心理学测试的游戏。需求简单来说就是：&lt;/p&gt;
&lt;p&gt;1. 游戏开始后轮转播放图片、视频或者音频 （媒体库要容易换，播放的切换间隙也要能配置）    &lt;br /&gt;2&amp;#160; 被试通过操控手中的手柄表达心理的反应，由程序转成可统计的数据（比如看到美女图按同时按下AB）     &lt;br /&gt;3. 程序得到的数据能够很容易的被统计，统计结果能够很优雅的呈现出来&lt;/p&gt;
&lt;p&gt;为了让这个事情变得更有趣，本座在需求确定之后决定：&lt;/p&gt;
&lt;p&gt;1. 用帅气的&lt;a href="http://www.nintendo.co.uk/NOE/en_GB/systems/accessories_1243.html" target="_blank"&gt;Wii Remote&lt;/a&gt;来让被试表达自己（想想美女图片一出就甩或者是撸一下WiiRemote有多实在）     &lt;br /&gt;2. 用&lt;a href="http://www.pygame.org/news.html" target="_blank"&gt;pyGame&lt;/a&gt;来写这个游戏（早就想学习pyGame了）     &lt;br /&gt;3. 把统计数据的输出作为一个用&lt;a href="http://www.r-project.org/" target="_blank"&gt;R语言&lt;/a&gt;实现的统计绘图的界面的输入&lt;/p&gt;
&lt;p&gt;接着就开始第一项。当程序把Wii Remote的蓝牙信号正确的转换成标准的手柄信号的时候，一看已经挺晚了，本座就只好把后面两个放在了todo list上。接着这两天都很忙这些东西就继续的呆在todo list。&lt;/p&gt;
&lt;p&gt;然后今天又找到时间，本座就开始用pyGame写游戏本身部分，但突然觉得vim下面自动补全很烂，就开始google合适的插件。花了10分钟左右发觉不少人说pydict好，本座就又花了15分钟左右去配置。然后看着chrome里面为了搜索插件弹出的一堆tab突然本座发现：&lt;/p&gt;
&lt;p&gt;经过了4天，本座把Wii Remote用蓝牙连到PC输出手柄信号，本座有了一个不错的vim下开发python的环境，本座还学习了一点儿R。唯一没有开始的就是，嗯，还没有开始写那个游戏。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;承&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;你的情况可能具体细节和我不一样，但是结果估计都是南辕北辙：你是网页设计师，在需要画wireframe的时候花了一大把时间去看搜索出来的新鲜的、华丽的CSS3效果；你上淘宝买手机结果研究移动电源用了4个小时；你想学怎么养花结果因为选盆子下面水漏的形状耽误了。&lt;/p&gt;
&lt;p&gt;这种情况之所以对你的效率有很大的伤害是因为：&lt;/p&gt;
&lt;p&gt;1. 你认为你是在完成自己todo list上的东西，所以你觉得自己是在“进展中”而不是“瞎逛”。    &lt;br /&gt;2. 你认为的进展给你带来了更多todo list上的东西，而且有些确实对原来的目标是无益的。&lt;/p&gt;
&lt;p&gt;人的精力是有限的，如果你长期处于这种状况（太正常了，如果你是玩电脑的话），可就要小心了。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;转&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;其实这种发散的工作方式并不是完全错误的。其实在我们这个行业，这种“总想追求更好”的想法，是整个Agile的基础。Facebook在自己的员工的邮件&lt;a href="http://blogs.wsj.com/deals/2012/02/01/mark-zuckerbergs-letter-from-the-facebook-filing/" target="_blank"&gt;里面&lt;/a&gt;写到：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The Hacker Way is an approach to building that involves continuous improvement and iteration. Hackers believe that something can always be better, and that nothing is ever complete. They just have to go fix it — often in the face of people who say it’s impossible or are content with the status quo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;从本座自己的感觉而言，做事循规蹈矩的同事，完成一般难度的任务时，效率确实很高。但是那种真正非常困难的问题，常常是被喜欢“瞎逛”的人解决的。这当然也没什么奇怪的，所谓闭门造的车，出门就只能合辙。Richard Hamming也&lt;a href="http://www.cs.virginia.edu/~robins/YouAndYourResearch.html" target="_blank"&gt;说&lt;/a&gt;：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I notice that if you have the door to your office closed, you get more work done today and tomorrow, and you are more productive than most. But 10 years later somehow you don&amp;#8217;t know quite about what problems are worth working on … He who works with the door open gets all kinds of interruptions, but he also occasionally gets clues as to what the world is and what might be important. ….&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;&lt;strong&gt;合&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;不能闭门造车，又需要有固定的输出值，怎么办？今天本座是这么办的：&lt;/p&gt;
&lt;p&gt;1. 早上起来把今天最重要的事情从&lt;a href="https://astrid.com/home" target="_blank"&gt;todo list&lt;/a&gt;里面选出来    &lt;br /&gt;2. 完成这些事情的过程中遇到任何有趣的东西或者想法，存到&lt;a href="http://delicious.com/" target="_blank"&gt;delicious&lt;/a&gt;或者&lt;a href="http://www.evernote.com/" target="_blank"&gt;evernote&lt;/a&gt;里面    &lt;br /&gt;3. 使用&lt;a href="https://idonethis.com" target="_blank"&gt;Done list&lt;/a&gt;而不是todo list来标记自己今天的活动&lt;/p&gt;
&lt;p&gt;结果是今天3点钟就完成了所有重要的事情，能够来安心的写一篇blog，看起来是个不错的办法。&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255123/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/03/use-done-list-rather-than-todo-list/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/03/use-done-list-rather-than-todo-list/feed/</wfw:commentRss><slash:comments>4</slash:comments><description>起 xkcd一直是本座最喜欢的网站（嗯哼）。上面这幅图说了一个很有趣的现象，正好最近深有体会，就来这边吐槽一下。整个经过是： 大前天回到家感觉不算太忙，本座就开始家姐布置的家庭作业：做一个用于心理学测试的游戏。需求简单来说就是： 1. 游戏开始后轮转播放图片、视频或者音频 （媒体库要容易换，播放的切换间隙也要能配置） 2&amp;#160; 被试通过操控手中的手柄表达心理的反应，由程序转成可统计的数据（比如看到美女图按同时按下AB） 3. 程序得到的数据能够很容易的被统计，统计结果能够很优雅的呈现出来 为了让这个事情变得更有趣，本座在需求确定之后决定： 1. 用帅气的Wii Remote来让被试表达自己（想想美女图片一出就甩或者是撸一下WiiRemote有多实在） 2. 用pyGame来写这个游戏（早就想学习pyGame了） 3. 把统计数据的输出作为一个用R语言实现的统计绘图的界面的输入 接着就开始第一项。当程序把Wii Remote的蓝牙信号正确的转换成标准的手柄信号的时候，一看已经挺晚了，本座就只好把后面两个放在了todo list上。接着这两天都很忙这些东西就继续的呆在todo list。 然后今天又找到时间，本座就开始用pyGame写游戏本身部分，但突然觉得vim下面自动补全很烂，就开始google合适的插件。花了10分钟左右发觉不少人说pydict好，本座就又花了15分钟左右去配置。然后看着chrome里面为了搜索插件弹出的一堆tab突然本座发现： 经过了4天，本座把Wii Remote用蓝牙连到PC输出手柄信号，本座有了一个不错的vim下开发python的环境，本座还学习了一点儿R。唯一没有开始的就是，嗯，还没有开始写那个游戏。 承 你的情况可能具体细节和我不一样，但是结果估计都是南辕北辙：你是网页设计师，在需要画wireframe的时候花了一大把时间去看搜索出来的新鲜的、华丽的CSS3效果；你上淘宝买手机结果研究移动电源用了4个小时；你想学怎么养花结果因为选盆子下面水漏的形状耽误了。 这种情况之所以对你的效率有很大的伤害是因为： 1. 你认为你是在完成自己todo list上的东西，所以你觉得自己是在“进展中”而不是“瞎逛”。 2. 你认为的进展给你带来了更多todo list上的东西，而且有些确实对原来的目标是无益的。 人的精力是有限的，如果你长期处于这种状况（太正常了，如果你是玩电脑的话），可就要小心了。 转 其实这种发散的工作方式并不是完全错误的。其实在我们这个行业，这种“总想追求更好”的想法，是整个Agile的基础。Facebook在自己的员工的邮件里面写到： The Hacker Way is an approach to building that involves continuous improvement and iteration. Hackers believe that something [...]&lt;img src="http://www1.feedsky.com/t1/643255123/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/03/use-done-list-rather-than-todo-list/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>productivity todo done</category><category>眉头一皱</category><pubDate>Fri, 16 Mar 2012 15:19:34 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/03/use-done-list-rather-than-todo-list/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=2024</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/03/use-done-list-rather-than-todo-list/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255123/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/03/use-done-list-rather-than-todo-list/</feedburner:origLink></item><item><title>盛世与盛名</title><link>http://feedproxy.google.com/~r/lenciel/~3/Aev6eMLddh4/</link><content:encoded>&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2012/03/400347ae115659100d3a14761dccb628303b2a96_m.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="400347ae115659100d3a14761dccb628303b2a96_m" border="0" alt="400347ae115659100d3a14761dccb628303b2a96_m" src="http://lenciel.cn/wp-content/uploads/2012/03/400347ae115659100d3a14761dccb628303b2a96_m_thumb.jpg" width="604" height="429" /&gt;&lt;/a&gt; 今年过年，春晚还是很难看，冠希又没有艳照看，还好大家都有微博看。&lt;/p&gt;
&lt;p&gt;要说微博上每天讨论的事情，确实挺让人费思量。什么“&lt;a href="http://www.google.com.hk/search?aq=f&amp;amp;ix=sea&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=%E6%96%B9%E9%9F%A9%E5%A4%A7%E6%88%98&amp;amp;qscrl=1" target="_blank"&gt;方韩大战&lt;/a&gt;”、&amp;quot;&lt;a href="http://www.google.com.hk/search?ix=sea&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=%E6%B5%99%E5%A4%A7+%E4%BD%95%E8%99%B9%E5%81%A5&amp;amp;qscrl=1&amp;amp;sei=syhTT5fJJ4G3iQequoXsCw&amp;amp;gbv=2" target="_blank"&gt;浙大高帅富&lt;/a&gt;”、“&lt;a href="http://www.google.com.hk/search?ix=sea&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=%E7%8E%8B%E7%AB%8B%E5%86%9B&amp;amp;qscrl=1&amp;amp;sei=oCpTT5GQGoSkiQexy9j9CQ&amp;amp;gbv=2" target="_blank"&gt;真汉子护士长&lt;/a&gt;”随便挑一个选题，够写一本书了 。可惜不管是哪个话题，总是高开低走，特别是方韩大战，到后面一些理论上脑子很正常的人都好像为朋友（其实也是自己）菊花插刀脑花凉拌了一样，搞得场面颇为惊悚。&lt;/p&gt;
&lt;p&gt;这两天微博上热门的话题变成了“&lt;a href="http://www.google.com.hk/search?hl=zh-CN&amp;amp;newwindow=1&amp;amp;safe=strict&amp;amp;qscrl=1&amp;amp;q=%E5%AD%A6%E9%9B%B7%E9%94%8B&amp;amp;oq=%E5%AD%A6%E9%9B%B7%E9%94%8B&amp;amp;aq=f&amp;amp;aqi=g10&amp;amp;aql=&amp;amp;gs_sm=3&amp;amp;gs_upl=48806l49506l0l50073l7l6l0l0l0l0l358l358l3-1l1l0&amp;amp;gs_l=serp.3..0l10.48806l49506l0l50073l7l6l0l0l0l0l358l358l3-1l1l0" target="_blank"&gt;学雷锋&lt;/a&gt;”，宣传和打倒的两派好不热闹。本座突然觉得，微博上每个话题看起来纷纷乱象，骨子里却自有它们的同一个爹妈：有什么样的盛世，就有什么样的盛名。&lt;/p&gt;
&lt;p&gt;我们从小受到的愚民教育，总把朝代的兴衰，历史的进退，摊派到带着好人坏人脸谱的个体，从来不从体制找原因。这种愚民教育的收获是，一般的老百姓对抗过日的国民党，救过国的李鸿章，有稀里糊涂的仇恨；对饿死了几千万人的老毛，或者搞过几次大镇压的小平，有懵里懵懂的敬爱。即便是段位相当高的学者，也不乏一说起大清的灭亡就怪慈禧，一说起文革的动乱就怨四人帮的糊涂蛋。打开漫漫五千年历史，对大多数中国人来说就像打开一副三国杀的纸牌，主公，忠臣，内奸和反贼，早就已经站好队归好位。&lt;/p&gt;
&lt;p&gt;为什么《&lt;a href="http://movie.douban.com/subject/2213597/" target="_blank"&gt;朗读者&lt;/a&gt;》这样的电影能得到大家的认可？因为不是脸谱戏。但是等大家都到电信缴了网费，在手机上装了微博，突然看到雷锋赖宁甚至主席总理们原来有这样那样的不一样的面目，大家的反应难免还是受扑克牌思维左右：如果他不是好的，就把他放到坏人的那堆。&lt;/p&gt;
&lt;p&gt;要知道孔老先生几千年前就站在还没有断流的河边说，“逝者如斯夫，不舍昼夜”。无论这路上有顺流、逆流、涡流还是湍流，两岸猿声啼不住，百川总要向东流。什么样的盛名总是产生在什么样的盛世，夸大个人对形势的推动能力，希望靠树立领袖偶像或者打击抹黑异己挽狂澜于即倒，没希望矣。&lt;/p&gt;
&lt;p&gt;不然你以为，香港廉政这么几十年，突然一坏，就坏在了特首身上，是因为出了个不知廉耻的特首？其实这是大陆官场侵蚀香港的必然结果，就算名声不是坏在曾哥身上，也会坏在春哥身上，时间问题而已。&lt;/p&gt;
&lt;p&gt;不然你以为，写一点擦边球嘻怒笑骂文章的赛车手，能有这几百万奉他为精神领袖的屁民粉丝？其实中国能有一点正常的民主生活，能有合法的政治漫画，电视台的脱口秀主持人能随时调侃一下各位后代都在美国开家长会的常委，赛车手也就能专心赛车了。&lt;/p&gt;
&lt;p&gt;不然你以为，雷锋能在朝廷要宣传他的时候勇敢的说不，我拒绝摆拍？那时候水灵灵的文工团姑娘陪主席跳舞跳到寝宫里去，不但不敢说不，还都觉得无上光荣呢。&lt;/p&gt;
&lt;p&gt;中国的希望，既不在于树立几个雷锋一样的偶像，更不在于打倒几个雷锋一样的偶像。现代社会靠的首先是制度不是道德。有制度，让写书的不抄书，蒙牛的不蒙人，打黑的不逼供，拼爹的不报送，一位老人不管在南海边划了一个圈还是下了一碗面，都不能让一部分人就先富起来，那才是中国人民站起来的时候。&lt;/p&gt;
&lt;p&gt;而且，这天总会来的。就连“自信人生二百年， 会当水击三千里”的开国皇帝， 还不是说驾崩就要驾崩。逆水行舟，可怜的是黎民百姓和底层官吏，可惜的是耗费的个人年华和社会资源。&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255124/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/03/about-fame/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/03/about-fame/feed/</wfw:commentRss><slash:comments>5</slash:comments><description>今年过年，春晚还是很难看，冠希又没有艳照看，还好大家都有微博看。 要说微博上每天讨论的事情，确实挺让人费思量。什么“方韩大战”、&amp;#34;浙大高帅富”、“真汉子护士长”随便挑一个选题，够写一本书了 。可惜不管是哪个话题，总是高开低走，特别是方韩大战，到后面一些理论上脑子很正常的人都好像为朋友（其实也是自己）菊花插刀脑花凉拌了一样，搞得场面颇为惊悚。 这两天微博上热门的话题变成了“学雷锋”，宣传和打倒的两派好不热闹。本座突然觉得，微博上每个话题看起来纷纷乱象，骨子里却自有它们的同一个爹妈：有什么样的盛世，就有什么样的盛名。 我们从小受到的愚民教育，总把朝代的兴衰，历史的进退，摊派到带着好人坏人脸谱的个体，从来不从体制找原因。这种愚民教育的收获是，一般的老百姓对抗过日的国民党，救过国的李鸿章，有稀里糊涂的仇恨；对饿死了几千万人的老毛，或者搞过几次大镇压的小平，有懵里懵懂的敬爱。即便是段位相当高的学者，也不乏一说起大清的灭亡就怪慈禧，一说起文革的动乱就怨四人帮的糊涂蛋。打开漫漫五千年历史，对大多数中国人来说就像打开一副三国杀的纸牌，主公，忠臣，内奸和反贼，早就已经站好队归好位。 为什么《朗读者》这样的电影能得到大家的认可？因为不是脸谱戏。但是等大家都到电信缴了网费，在手机上装了微博，突然看到雷锋赖宁甚至主席总理们原来有这样那样的不一样的面目，大家的反应难免还是受扑克牌思维左右：如果他不是好的，就把他放到坏人的那堆。 要知道孔老先生几千年前就站在还没有断流的河边说，“逝者如斯夫，不舍昼夜”。无论这路上有顺流、逆流、涡流还是湍流，两岸猿声啼不住，百川总要向东流。什么样的盛名总是产生在什么样的盛世，夸大个人对形势的推动能力，希望靠树立领袖偶像或者打击抹黑异己挽狂澜于即倒，没希望矣。 不然你以为，香港廉政这么几十年，突然一坏，就坏在了特首身上，是因为出了个不知廉耻的特首？其实这是大陆官场侵蚀香港的必然结果，就算名声不是坏在曾哥身上，也会坏在春哥身上，时间问题而已。 不然你以为，写一点擦边球嘻怒笑骂文章的赛车手，能有这几百万奉他为精神领袖的屁民粉丝？其实中国能有一点正常的民主生活，能有合法的政治漫画，电视台的脱口秀主持人能随时调侃一下各位后代都在美国开家长会的常委，赛车手也就能专心赛车了。 不然你以为，雷锋能在朝廷要宣传他的时候勇敢的说不，我拒绝摆拍？那时候水灵灵的文工团姑娘陪主席跳舞跳到寝宫里去，不但不敢说不，还都觉得无上光荣呢。 中国的希望，既不在于树立几个雷锋一样的偶像，更不在于打倒几个雷锋一样的偶像。现代社会靠的首先是制度不是道德。有制度，让写书的不抄书，蒙牛的不蒙人，打黑的不逼供，拼爹的不报送，一位老人不管在南海边划了一个圈还是下了一碗面，都不能让一部分人就先富起来，那才是中国人民站起来的时候。 而且，这天总会来的。就连“自信人生二百年， 会当水击三千里”的开国皇帝， 还不是说驾崩就要驾崩。逆水行舟，可怜的是黎民百姓和底层官吏，可惜的是耗费的个人年华和社会资源。&lt;img src="http://www1.feedsky.com/t1/643255124/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/03/about-fame/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>两腿一张</category><category>学雷锋</category><pubDate>Mon, 05 Mar 2012 12:52:13 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/03/about-fame/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=2018</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/03/about-fame/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255124/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/03/about-fame/</feedburner:origLink></item><item><title>Android开发中使用ProGuard</title><link>http://feedproxy.google.com/~r/lenciel/~3/olzcl6ad-KI/</link><content:encoded>&lt;p&gt;今天被同事问到怎么在release版本里面所有的log都去掉的时候，竟然只能回忆起用ProGuard做过这个，完全忘记怎么做的了，特立此存照。文章里面使用的例子放在&lt;a class="network" href="https://github.com/lenciel/AMP" rel="me"&gt;&lt;img src="http://lenciel.cn/wp-content/themes/lenciel/images/github_button.png" alt="" width="16" height="16" /&gt; Android-Maven-ProGuard-Sample-App&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/p&gt;
&lt;h4&gt;ProGuard简介&lt;/h4&gt;
&lt;p&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在移动设备上面开发应用程序，性能是一个很关键的指标。你的老板走过来要你提高性能的时候，你的第一反应有可能是抓起熟悉的工具花几个小时profile自己的应用，找出那些时间都花在哪里了。在使用这么终极的手段之前，千万不要忘记了先试试ProGuard。&lt;/p&gt;
&lt;p&gt;做Android之前就是Java程序员的可能早就已经对ProGuard很熟悉了。简单的来说，ProGuard就是一个Java的class文件处理器，主要的功能类似奥运会口号：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;让你的程序变得更小更快 &lt;/li&gt;
&lt;li&gt;让你的程序变得更难被反向工程 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尽管ProGuard不是专用于Android开发的，但是在Android的SDK里面已经包括了这个工具，路径是&lt;code&gt;ANDROID_HOME/tools/proguard&lt;/code&gt;，文档可以在&lt;a href="http://proguard.sourceforge.net"&gt;http://proguard.sourceforge.net&lt;/a&gt;看到。&lt;/p&gt;
&lt;p&gt;让程序变得更小更快的好处是不言而喻的。ProGuard通过对bytecode进行优化，优化手段包括去掉无用的代码，去掉内联方法的调用，对类的继承结构进行优化，把所有能加上的&lt;code&gt;final&lt;/code&gt;和&lt;code&gt;static&lt;/code&gt;加上，以及对算术运算进行&lt;a href="http://en.wikipedia.org/wiki/Peephole_optimization" target="_blank"&gt;Peephole optimization&lt;/a&gt;等等。&lt;/p&gt;
&lt;p&gt;让程序变得更难被反向工程就不一定是每个人都需要的了。一般情况下，对Android的反向工程是把Dalvik的bytecode转换成Java的bytecode，然后使用传统的Java反向工具转成成Java源代码。如果你的项目是开源的，显然也没有必要防止别人反向。但是如果是下面几种情况，你就很可能需要它了： &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你在源文件里面有一些不想被别人看到的信息，如密码等 &lt;/li&gt;
&lt;li&gt;你的代码里面有自己或者公司的赖以生存的知识产权 &lt;/li&gt;
&lt;li&gt;你的甲方有明确的要求 &lt;/li&gt;
&lt;li&gt;你的程序按license等方式收费，你不想被别人把licens检查的部分去掉重新编译个版本 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ProGuard可以帮助通过对类，方法和成员名称进行混淆，同时通过去掉结构化的信息，如文件名或者行号表等，来使得代码从理论上变得不可被反向工程。&lt;/p&gt;
&lt;p&gt;如此看来，ProGuard真是美好事物一枚。但是ProGuard也不是随手一点药到病除的，也有一点学习曲线。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/p&gt;
&lt;h4&gt;启用ProGuard&lt;/h4&gt;
&lt;p&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果你使用Eclipse的ADT，每个新建的项目都会生成一个&lt;code&gt;proguard.cfg&lt;/code&gt;文件在项目的根目录。你对ProGuard的所有设定就是在这个文件里面完成的。要想在项目里面启用Proguard，只需要把同样在项目根目录的&lt;code&gt;default.properties&lt;/code&gt;里面加上：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;proguard.config=proguard.cfg&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;当然，如果你蛋疼到要自己去移动cfg文件的位置，也要记得去改等号后面的部分。然后，在所有的release版本的build里，你的Proguard就已经生效了。对于使用Eclipse的同学来说，release的build就是指通过选择Android Tools&amp;gt;Export Signed/Unsigned Application Package来进行。&lt;/p&gt;
&lt;p&gt;因为在大多数开发中我们都会使用Ant或者是Maven来对项目进行管理，所以一般不会直接用Eclipse来进行release版本的编译，所以通常我们还要掌握如何在不使用ADT的情况下使用ProGuard。对于Maven而言，可以通过使用Maven Android plugin来完成。同时，由于ProGuard已经完全集成到Android的工具链里面了，所以Android的Ant任务里面也有一个专门的private任务叫做&lt;code&gt;-obfuscate&lt;/code&gt;，会把激活并使用ProGuard作为release这个target的一部分，所以使用Ant的话只要一个ant release就可以了。&lt;/p&gt;
&lt;p&gt;当ProGuard执行以后，会产生几个特别重要的文件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mapping.txt：保存了混淆后的名字和混淆前名字的对应关系。&lt;strong&gt;对于每次release的build，都要记得保存这个文件&lt;/strong&gt;，要不然如果你收到release版本上报出的defect的时候，就等着哭吧。 &lt;/li&gt;
&lt;li&gt;seeds.txt：ProGuard找到的你的程序的entrypoint列表。 &lt;/li&gt;
&lt;li&gt;usage.txt：ProGuard觉得没有用所以移除了的一堆类，域和方法的list。要想学习写作“完美”的ProGuard规则的同学就要经常来这个文件看看自己定下的rule对ProGuard的行为究竟有什么样的影响。如果你有用的类出现在list里面了，说明你削得太猛了，反之亦然。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;需要注意的是这些文件的输出目录。在使用Ant ProGuard target的时候，输出目录是&lt;code&gt;bin/proguard/&lt;/code&gt;，但是如果是通过ADT(右键project&amp;gt;Android Tools&amp;gt;Export）的话，输出目录会是&lt;code&gt;proguard/&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;还有一个常见的困惑就是ProGuard是怎么找到那些需要处理的文件的。一般情况下，ProGuard希望你用&lt;code&gt;-injars&lt;/code&gt;或者是&lt;code&gt;-libraryjars&lt;/code&gt;来告诉它。但是对Android开发而言，Ant任务和ADT都会自动的查看你的&lt;code&gt;libs&lt;/code&gt;，&lt;code&gt;output&lt;/code&gt;和项目的&lt;code&gt;classpath&lt;/code&gt;目录。&lt;/p&gt;
&lt;p&gt;从执行过程的日志来看，ProGuard对类文件的操作分为三个步骤：shrink，optimize，obfuscate。每个步骤都是可选的，可以通过使用&lt;code&gt;-dontshrink&lt;/code&gt;、&lt;code&gt;-dontoptimize&lt;/code&gt;和&lt;code&gt;-dontobfuscate&lt;/code&gt;来分别关掉。一般来说，不用因为结果“不如人意”就随意的关掉某个步骤。完整的进行三个步骤，然后不断的改变规则，直到达到最佳效果，是使用ProGuard的最佳方式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/p&gt;
&lt;h4&gt;编写ProGuard规则&lt;/h4&gt;
&lt;p&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ProGuard和很多工具一样，其强大之处在于选项够多。作为Android开发者使用，首先心里要明白，没有一个唯一的最佳配置规则。在此基础上，去掌握一些对Android程序而言通常是适用的规则。然后，就像在文章里面已经反复强调过的一样，以这些规则为起点，反复的调整你的规则，找出一个对自己的程序最适用的规则。&lt;/p&gt;
&lt;p&gt;当然，因为选项太多，ProGuard给初学者的感觉难免是千头万绪，无从下手。因此，我们可以从一个例子程序入手来找到对ProGuard的“感觉”。&lt;/p&gt;
&lt;p&gt;这个例子本身没有任何特别之处，&lt;code&gt;MyButton&lt;/code&gt;类继承自&lt;code&gt;Button&lt;/code&gt;但是没有添加新的方法，可以通过它来观察ProGuard如何对继承结构进行压缩。Click的handler除开显示toast之外也没有特别的功能，可以通过它来观察ProGuard对方法名的混淆。&lt;code&gt;AMPSampleActivity&lt;/code&gt;里面还专门有一个没有被调用的方法，可以通过它来观察ProGuard对这种情况的处理。下面是程序的入口Activity的实现：&lt;/p&gt;
&lt;p&gt;我们期望ProGuard做的事情包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;保留&lt;code&gt;AMPSampleActivity&lt;/code&gt;类，因为它是我们在XML里面指定的程序入口 &lt;/li&gt;
&lt;li&gt;保留&lt;code&gt;StringUtils&lt;/code&gt;类和它的&lt;code&gt;repeat&lt;/code&gt;方法 &lt;/li&gt;
&lt;li&gt;保留&lt;code&gt;myClickHandler&lt;/code&gt;方法 &lt;/li&gt;
&lt;li&gt;保留&lt;code&gt;MyButton&lt;/code&gt;类 &lt;/li&gt;
&lt;li&gt;去掉&lt;code&gt;unusedMethod&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;除开XML里面引用的类（&lt;code&gt;AMPSampleActivity&lt;/code&gt;和&lt;code&gt;MyButton&lt;/code&gt;），其他的类名都需要被混淆 &lt;/li&gt;
&lt;li&gt;除开XML里面引用的方法名（&lt;code&gt;myClickHandler&lt;/code&gt;），其他的方法名都要被混淆 &lt;/li&gt;
&lt;li&gt;完成一些对Android而言通常适用的优化（下面会仔细展开） &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ProGuard的规则是“白名单”的，也就是说ProGuard只会对你特别指定的类刀下开恩。这也就是说，对任何程序，我们都至少要写一条规则，来保留程序的入口类。因为是Android程序，我们可以这么写：&lt;/p&gt;
&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keep public class * extends android.app.Activity&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;这里我们可以看到ProGuard的rule用的语法基本上遵循了Java本身的语法（extends等等），但是它支持使用通配符。规则中的-keep告诉ProGuard不要删除也不要混淆任何从android.app.Activity继承的类。&lt;/p&gt;
&lt;p&gt;很简单，不是吗？如果你这个时候运行程序，会看到： &lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;    org.lenciel.android/org.lenciel.android.AMPSampleActivity&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;: 
    ➥ android.view.InflateException: Binary XML file line &lt;span style="color: #adadad; font-style: italic;"&gt;#6: Error inflating &lt;/span&gt;
    ➥ class org.lenciel.android.MyButton&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;为什么在inflate我们自定义的view的时候crash了呢？这是因为自定义的view是在XML里面被用到的，而不是在Java代码里面。因此ProGuard会认为这是没有用的代码而试着删除它。要保证这些自定义的view不被误删，就需要定义如下的规则：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keepclasseswithmembers class * &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    public &amp;lt;init&amp;gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;android.content.Context, android.util.AttributeSet&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt; 
&amp;nbsp;
-keepclasseswithmembers class * &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    public &amp;lt;init&amp;gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;android.content.Context, android.util.AttributeSet, int&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;这两条规则告诉ProGuard不要对定义了可能被&lt;code&gt;LayoutInflater&lt;/code&gt;调用的构造函数的任何类进行优化。我们这里使用了&lt;code&gt;-keepclasseswithmembers&lt;/code&gt;而不是&lt;code&gt;-keep&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;再次运行，会遇到下面的错误：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;java.lang.IllegalStateException: Could not find a method 
   ➥ myClickHandler&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;View&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; in the activity class org.lenciel.android.AMPSampleActivity for onClick handler on 
   ➥ view class org.lenciel.android.MyButton&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;去查看&lt;code&gt;usage.txt&lt;/code&gt;你会发现&lt;code&gt;myClickHandler&lt;/code&gt;又被干掉了。为什么在第一条规则里面我们告诉ProGuard不要动&lt;code&gt;AMPSampleActivity&lt;/code&gt;里面的任何东西，还是会有这种情况发生？这是使用&lt;code&gt;-keep&lt;/code&gt;的一个常见的误会。我们用&lt;code&gt;-keep&lt;/code&gt;告诉ProGuard保留一个类的时候，没有提供任何类的“body”信息的话，ProGuard仅仅会保留这个类的名字。它仍然会对这个类内部的所有东西进行优化和混淆。要保留方法，我们需要这么写：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keep public class * extends android.app.Activity &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; 
    methods; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;但是这样写显然又太过于慷慨了。下面这条规则会好很多：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keepclassmembers class * extends android.app.Activity &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    public void *&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;android.view.View&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;这条规则告诉ProGuard，如果一个&lt;code&gt;Activity&lt;/code&gt;在&lt;code&gt;shrink&lt;/code&gt;阶段没有被去掉，那么就保留那些&lt;code&gt;public&lt;/code&gt;的，没有返回值的，传入了&lt;code&gt;android.view.View&lt;/code&gt;作为参数的方法。&lt;/p&gt;
&lt;p&gt;可以看到，使用ProGuard存在一个不断调优的过程。他山之石，可以攻玉，已经有很多人使用ProGuard来优化Android程序了，于是也有了一些被普遍采用的规则和选项，我们下面来个简单说明。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/p&gt;
&lt;h4&gt;常用规则和选项&lt;/h4&gt;
&lt;p&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;前面看到的规则对于例子程序就足够了。但是如果我们的程序使用了&lt;code&gt;Service&lt;/code&gt;怎么办？和&lt;code&gt;Activity&lt;/code&gt;一样，&lt;code&gt;Service&lt;/code&gt;也是在manifest xml里面定义的，因此我们需要对&lt;code&gt;proguard.cfg&lt;/code&gt;做一定的扩展。&lt;/p&gt;
&lt;p&gt;下面的规则是针对Android程序一般来说都比较有效的。&lt;/p&gt;
&lt;p&gt;一般来说，下面的Android framework class都是需要保留的：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keep public class * extends android.app.Activity 
-keep public class * extends android.app.Application 
-keep public class * extends android.app.Service 
-keep public class * extends android.content.BroadcastReceiver 
-keep public class * extends android.content.ContentProvider 
-keep public class * extends android.app.backup.BackupAgentHelper 
-keep public class * extends android.preference.Preference 
-keep public class com.android.vending.licensing.ILicensingService&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;虽然你的程序可能一开始没有使用其中的一些类，但是定义好全部这些规则也是有好处的：它可以避免你在使用ProGuard编出的版本crash之后去搞半天才发现有某个类似的规则需要更新但是你忘记了。&lt;/p&gt;
&lt;p&gt;第二个有用的规则是保留&lt;code&gt;static&lt;/code&gt;的&lt;code&gt;CREATOR&lt;/code&gt;域，这个是Android用来parcel对象的。这个域由于是在运行的时候&lt;a href="http://www.google.com.hk/url?sa=t&amp;amp;rct=j&amp;amp;q=introspection&amp;amp;source=web&amp;amp;cd=2&amp;amp;ved=0CDYQFjAB&amp;amp;url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FIntrospection&amp;amp;ei=_JhDT-6ADIGtiQfF46TMBA&amp;amp;usg=AFQjCNEEE1rrErPfi38AVCPjdN6ri-qROA" target="_blank"&gt;Instrospection&lt;/a&gt;的，所以ProGuard会认为它是无用的域并把它去掉。下面这条rule可以防止这样的事情发生：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keepclassmembers class * implements android.os.Parcelable &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    static android.os.Parcelable$Creator CREATOR; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;在程序中如果你调用了native的code，比如你用JNI来调用了c的lib，由于在Java代码里面是一份方法的签名，而没有方法的实现，它必须被链接到native code上。这也就意味着这些函数名不能被ProGuard加以混淆了，不然链接的过程就会失败。下面的规则可以保证ProGuard不去动native的方法名：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keepclasseswithmembernames class * &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; 
     native methods; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;我们这里使用的&lt;code&gt;-keepclasseswithmembernames&lt;/code&gt;是告诉ProGuard，被调用过的方法留着，没有调用过的都去掉。&lt;/p&gt;
&lt;p&gt;前面的规则看起来都一目了然。下面这个可能要费解一些：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keepclassmembers enum * &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;   
     public static **&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; values&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; 
     public static ** valueOf&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;java.lang.String&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; 
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;这个规则是让ProGuard不要去动任何&lt;code&gt;Enum&lt;/code&gt;的&lt;code&gt;values&lt;/code&gt;和&lt;code&gt;valueOf&lt;/code&gt;方法。这些方法之所以特殊是因为Java自己是通过发射机制来调用它们的。这可能也是Google&lt;a href="https://developer.android.com/guide/practices/design/performance.html#avoid_enums" target="_blank"&gt;不建议使用&lt;/a&gt;Java enum的原因吧：它们比&lt;code&gt;final class fields&lt;/code&gt;的性能要低不少。如果你已经遵照Google的教诲停止使用&lt;code&gt;Enum&lt;/code&gt;，那你也不需要这条规则了，恭喜。&lt;/p&gt;
&lt;p&gt;下面来看看常用的选项：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-dontusemixedcaseclassnames 
-dontskipnonpubliclibraryclasses 
-dontpreverify 
-verbose&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;第一个选项可以避免像Windows这样不区分大小写的操作系统不会因为类似&lt;code&gt;A.class&lt;/code&gt;和&lt;code&gt;a.class&lt;/code&gt;写到同一个文件里面就驾崩。&lt;/p&gt;
&lt;p&gt;第二个选项是因为ProGuard默认不会处理任何非public的类。但是有时候我们会遇到public的类继承自内部的非public的类。所以打开这个选项可以更好的覆盖。&lt;/p&gt;
&lt;p&gt;第三个选项是告诉ProGuard不要做&lt;code&gt;preverify&lt;/code&gt;（预检验），因为这个只对J2ME或者是Java6的平台有用。&lt;/p&gt;
&lt;p&gt;最后一个选项，你们懂的。&lt;/p&gt;
&lt;p&gt;前面我们提到过ProGuard有一个优化代码（optimize）的过程。大多数时候ProGuard都会火力全开的对所有的代码做优化。这些优化操作有些时候是相当aggressive的，比如合并类的时候ProGuard会试着既从纵向上合并也从横向上合并，以便得到尽量少的类文件，也就可以得到尽量小的APK。同时它还会试着优化循环和代数运算。默认的ADT生成的ProGuard选项关掉了很多的优化选项：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;Google并没有提供他们这么配置的依据。我们可以试着先禁用这个选项，看看程序运行起来会不会有问题。如果遇到了问题再试着慢慢的减弱优化，来“探底”。&lt;/p&gt;
&lt;p&gt;同时ProGuard的优化是可以“递归”的，也就是优化完的结果可以作为下次优化的输入继续优化。你可以指定它反复进行多少次。但ProGuard如果发现已经没有什么可以优化，会自动停下来，不一定跑到你指定的次数。一般设置成5就够了：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-optimizationpasses &lt;span style="color: #cc66cc;"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/p&gt;
&lt;h4&gt;如果处理混淆后版本的错误报告&lt;/h4&gt;
&lt;p&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果你发布了混淆的版本，有一个问题你就得面对：用户提交的问题单里面产生自这些类和方法都完全打乱过后的版本。为了展示这种问题，在Demo程序里面专门加了这么一个类：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="java" style="font-family:monospace;"&gt;&lt;span style="color: #FFA500; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #FFA500; font-weight: bold;"&gt;class&lt;/span&gt; Bomb &lt;span style="color: #009900;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #FFA500; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #FFA500; font-weight: bold;"&gt;void&lt;/span&gt; explode&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt; &lt;span style="color: #009900;"&gt;&amp;#123;&lt;/span&gt;
        &lt;span style="color: #FFA500; font-weight: bold;"&gt;throw&lt;/span&gt; &lt;span style="color: #FFA500; font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: #003399;"&gt;RuntimeException&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;quot;Boom!&amp;quot;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&amp;#125;&lt;/span&gt;
&lt;span style="color: #009900;"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;在onCreate方法里面它会被引爆：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="java" style="font-family:monospace;"&gt;&lt;span style="color: #FFA500; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #FFA500; font-weight: bold;"&gt;void&lt;/span&gt; onCreate&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;Bundle savedInstanceState&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt; &lt;span style="color: #009900;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #FFA500; font-weight: bold;"&gt;super&lt;/span&gt;.&lt;span style="color: #90EE90;"&gt;onCreate&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;savedInstanceState&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    setContentView&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;R.&lt;span style="color: #90EE90;"&gt;layout&lt;/span&gt;.&lt;span style="color: #90EE90;"&gt;main&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #003399;"&gt;String&lt;/span&gt; toast &lt;span style="color: #339933;"&gt;=&lt;/span&gt; StringUtils.&lt;span style="color: #90EE90;"&gt;repeat&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;quot;Hello ProGuard! &amp;quot;&lt;/span&gt;, &lt;span style="color: #cc66cc;"&gt;3&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    Toast.&lt;span style="color: #90EE90;"&gt;makeText&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #FFA500; font-weight: bold;"&gt;this&lt;/span&gt;, toast, Toast.&lt;span style="color: #90EE90;"&gt;LENGTH_SHORT&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;.&lt;span style="color: #90EE90;"&gt;show&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #FFA500; font-weight: bold;"&gt;new&lt;/span&gt; Bomb&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;.&lt;span style="color: #90EE90;"&gt;explode&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #009900;"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;如果你运行程序，就会看到下面的错误：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;java.lang.RuntimeException: Unable to start activity ...MainActivity&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;: 
java.lang.RuntimeException: Boom!
...
Caused by: java.lang.RuntimeException: Boom!
   at org.lenciel.android.MainActivity.onCreate&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;Unknown Source&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
   at android.app.Instrumentation.callActivityOnCreate&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
   ➥ Instrumentation.java:&lt;span style="color: #cc66cc;"&gt;1047&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
   at android.app.ActivityThread.performLaunchActivity&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
   ➥ ActivityThread.java:&lt;span style="color: #cc66cc;"&gt;2627&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
   ... &lt;span style="color: #cc66cc;"&gt;11&lt;/span&gt; more&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;可以看到在错误出现位置的stack trace既没有行号也没有文件名。这是因为相关的信息都被ProGuard优化掉了。如果我们想避免这种情况，就要在&lt;code&gt;proguard.cfg&lt;/code&gt;里面加上下面的选项：&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;-keepattributes SourceFile,LineNumberTable&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/p&gt;
&lt;p&gt;显然，有了行号和文件名，还是解决不了方法被混淆的问题。我们这个例子程序里面方法很少，而&lt;code&gt;onCreate&lt;/code&gt;方法因为是&lt;code&gt;Override&lt;/code&gt;的，所以ProGuard不会去动它。如果是正式的工程，最好的办法还是用&lt;code&gt;retrace&lt;/code&gt;工具来根据&lt;code&gt;mapping.txt&lt;/code&gt;还原整个日志。&lt;/p&gt;
&lt;p&gt;
&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="xorg_conf" style="font-family:monospace;"&gt;$ retrace proguard/mapping.txt stacktrace.txt&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255125/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/02/android-maven-proguard-integration/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/02/android-maven-proguard-integration/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>今天被同事问到怎么在release版本里面所有的log都去掉的时候，竟然只能回忆起用ProGuard做过这个，完全忘记怎么做的了，特立此存照。文章里面使用的例子放在 Android-Maven-ProGuard-Sample-App ProGuard简介 在移动设备上面开发应用程序，性能是一个很关键的指标。你的老板走过来要你提高性能的时候，你的第一反应有可能是抓起熟悉的工具花几个小时profile自己的应用，找出那些时间都花在哪里了。在使用这么终极的手段之前，千万不要忘记了先试试ProGuard。 做Android之前就是Java程序员的可能早就已经对ProGuard很熟悉了。简单的来说，ProGuard就是一个Java的class文件处理器，主要的功能类似奥运会口号： 让你的程序变得更小更快 让你的程序变得更难被反向工程 尽管ProGuard不是专用于Android开发的，但是在Android的SDK里面已经包括了这个工具，路径是ANDROID_HOME/tools/proguard，文档可以在http://proguard.sourceforge.net看到。 让程序变得更小更快的好处是不言而喻的。ProGuard通过对bytecode进行优化，优化手段包括去掉无用的代码，去掉内联方法的调用，对类的继承结构进行优化，把所有能加上的final和static加上，以及对算术运算进行Peephole optimization等等。 让程序变得更难被反向工程就不一定是每个人都需要的了。一般情况下，对Android的反向工程是把Dalvik的bytecode转换成Java的bytecode，然后使用传统的Java反向工具转成成Java源代码。如果你的项目是开源的，显然也没有必要防止别人反向。但是如果是下面几种情况，你就很可能需要它了： 你在源文件里面有一些不想被别人看到的信息，如密码等 你的代码里面有自己或者公司的赖以生存的知识产权 你的甲方有明确的要求 你的程序按license等方式收费，你不想被别人把licens检查的部分去掉重新编译个版本 ProGuard可以帮助通过对类，方法和成员名称进行混淆，同时通过去掉结构化的信息，如文件名或者行号表等，来使得代码从理论上变得不可被反向工程。 如此看来，ProGuard真是美好事物一枚。但是ProGuard也不是随手一点药到病除的，也有一点学习曲线。 启用ProGuard 如果你使用Eclipse的ADT，每个新建的项目都会生成一个proguard.cfg文件在项目的根目录。你对ProGuard的所有设定就是在这个文件里面完成的。要想在项目里面启用Proguard，只需要把同样在项目根目录的default.properties里面加上： proguard.config=proguard.cfg 当然，如果你蛋疼到要自己去移动cfg文件的位置，也要记得去改等号后面的部分。然后，在所有的release版本的build里，你的Proguard就已经生效了。对于使用Eclipse的同学来说，release的build就是指通过选择Android Tools&amp;#62;Export Signed/Unsigned Application Package来进行。 因为在大多数开发中我们都会使用Ant或者是Maven来对项目进行管理，所以一般不会直接用Eclipse来进行release版本的编译，所以通常我们还要掌握如何在不使用ADT的情况下使用ProGuard。对于Maven而言，可以通过使用Maven Android plugin来完成。同时，由于ProGuard已经完全集成到Android的工具链里面了，所以Android的Ant任务里面也有一个专门的private任务叫做-obfuscate，会把激活并使用ProGuard作为release这个target的一部分，所以使用Ant的话只要一个ant release就可以了。 当ProGuard执行以后，会产生几个特别重要的文件： mapping.txt：保存了混淆后的名字和混淆前名字的对应关系。对于每次release的build，都要记得保存这个文件，要不然如果你收到release版本上报出的defect的时候，就等着哭吧。 seeds.txt：ProGuard找到的你的程序的entrypoint列表。 usage.txt：ProGuard觉得没有用所以移除了的一堆类，域和方法的list。要想学习写作“完美”的ProGuard规则的同学就要经常来这个文件看看自己定下的rule对ProGuard的行为究竟有什么样的影响。如果你有用的类出现在list里面了，说明你削得太猛了，反之亦然。 需要注意的是这些文件的输出目录。在使用Ant ProGuard target的时候，输出目录是bin/proguard/，但是如果是通过ADT(右键project&amp;#62;Android Tools&amp;#62;Export）的话，输出目录会是proguard/。 还有一个常见的困惑就是ProGuard是怎么找到那些需要处理的文件的。一般情况下，ProGuard希望你用-injars或者是-libraryjars来告诉它。但是对Android开发而言，Ant任务和ADT都会自动的查看你的libs，output和项目的classpath目录。 从执行过程的日志来看，ProGuard对类文件的操作分为三个步骤：shrink，optimize，obfuscate。每个步骤都是可选的，可以通过使用-dontshrink、-dontoptimize和-dontobfuscate来分别关掉。一般来说，不用因为结果“不如人意”就随意的关掉某个步骤。完整的进行三个步骤，然后不断的改变规则，直到达到最佳效果，是使用ProGuard的最佳方式。 编写ProGuard规则 ProGuard和很多工具一样，其强大之处在于选项够多。作为Android开发者使用，首先心里要明白，没有一个唯一的最佳配置规则。在此基础上，去掌握一些对Android程序而言通常是适用的规则。然后，就像在文章里面已经反复强调过的一样，以这些规则为起点，反复的调整你的规则，找出一个对自己的程序最适用的规则。 当然，因为选项太多，ProGuard给初学者的感觉难免是千头万绪，无从下手。因此，我们可以从一个例子程序入手来找到对ProGuard的“感觉”。 这个例子本身没有任何特别之处，MyButton类继承自Button但是没有添加新的方法，可以通过它来观察ProGuard如何对继承结构进行压缩。Click的handler除开显示toast之外也没有特别的功能，可以通过它来观察ProGuard对方法名的混淆。AMPSampleActivity里面还专门有一个没有被调用的方法，可以通过它来观察ProGuard对这种情况的处理。下面是程序的入口Activity的实现： 我们期望ProGuard做的事情包括： 保留AMPSampleActivity类，因为它是我们在XML里面指定的程序入口 保留StringUtils类和它的repeat方法 保留myClickHandler方法 保留MyButton类 去掉unusedMethod 除开XML里面引用的类（AMPSampleActivity和MyButton），其他的类名都需要被混淆 除开XML里面引用的方法名（myClickHandler），其他的方法名都要被混淆 完成一些对Android而言通常适用的优化（下面会仔细展开） ProGuard的规则是“白名单”的，也就是说ProGuard只会对你特别指定的类刀下开恩。这也就是说，对任何程序，我们都至少要写一条规则，来保留程序的入口类。因为是Android程序，我们可以这么写： -keep public [...]&lt;img src="http://www1.feedsky.com/t1/643255125/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/02/android-maven-proguard-integration/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>档案一理</category><category>android maven proguard tutorial</category><pubDate>Mon, 27 Feb 2012 19:06:45 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/02/android-maven-proguard-integration/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=2003</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/02/android-maven-proguard-integration/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255125/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/02/android-maven-proguard-integration/</feedburner:origLink></item><item><title>Icon Font</title><link>http://feedproxy.google.com/~r/lenciel/~3/Q9gOmvT0uDk/</link><content:encoded>&lt;div&gt;
&lt;p&gt;最近收集了一些&lt;a href="http://delicious.com/stacks/view/F4tX2W" target="_blank"&gt;Icon Font&lt;/a&gt;准备自己的项目里面用（这也是本座因为Stack功能切换回Delicious来管理书签之后第建的第一个&lt;a href="http://delicious.com/help#title1" target="_blank"&gt;Stack&lt;/a&gt;）。Icon Font本身看起来和普通的icon没有特别的差别：
&lt;/p&gt;
&lt;section id="see" class="see"&gt;
&lt;div class="content"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="icon"&gt;+&lt;/span&gt;
&lt;div class="tooltip"&gt;Add&lt;br /&gt;&lt;span class="character"&gt;+&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⊕&lt;/span&gt;
&lt;div class="tooltip"&gt;Add-alt&lt;br /&gt;&lt;span class="character"&gt;⊕&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;a&lt;/span&gt;
&lt;div class="tooltip"&gt;Alert&lt;br /&gt;&lt;span class="character"&gt;a&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;←&lt;/span&gt;
&lt;div class="tooltip"&gt;Arrow-left&lt;br /&gt;&lt;span class="character"&gt;←&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;→&lt;/span&gt;
&lt;div class="tooltip"&gt;Arrow-right&lt;br /&gt;&lt;span class="character"&gt;→&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;↑&lt;/span&gt;
&lt;div class="tooltip"&gt;Arrow-up&lt;br /&gt;&lt;span class="character"&gt;↑&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;↓&lt;/span&gt;
&lt;div class="tooltip"&gt;Arrow-down&lt;br /&gt;&lt;span class="character"&gt;↓&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;A&lt;/span&gt;
&lt;div class="tooltip"&gt;Attachment&lt;br /&gt;&lt;span class="character"&gt;A&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;↩&lt;/span&gt;
&lt;div class="tooltip"&gt;Back&lt;br /&gt;&lt;span class="character"&gt;↩&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;b&lt;/span&gt;
&lt;div class="tooltip"&gt;Bookmark&lt;br /&gt;&lt;span class="character"&gt;b&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;B&lt;/span&gt;
&lt;div class="tooltip"&gt;Bubble&lt;br /&gt;&lt;span class="character"&gt;B&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;c&lt;/span&gt;
&lt;div class="tooltip"&gt;Cart&lt;br /&gt;&lt;span class="character"&gt;c&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;C&lt;/span&gt;
&lt;div class="tooltip"&gt;Chart&lt;br /&gt;&lt;span class="character"&gt;C&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;✔&lt;/span&gt;
&lt;div class="tooltip"&gt;Check&lt;br /&gt;&lt;span class="character"&gt;✔&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⌚&lt;/span&gt;
&lt;div class="tooltip"&gt;Clock&lt;br /&gt;&lt;span class="character"&gt;⌚&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;☁&lt;/span&gt;
&lt;div class="tooltip"&gt;Cloud&lt;br /&gt;&lt;span class="character"&gt;☁&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;×&lt;/span&gt;
&lt;div class="tooltip"&gt;Delete&lt;br /&gt;&lt;span class="character"&gt;×&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⊗&lt;/span&gt;
&lt;div class="tooltip"&gt;Delete-alt&lt;br /&gt;&lt;span class="character"&gt;⊗&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;d&lt;/span&gt;
&lt;div class="tooltip"&gt;Denied&lt;br /&gt;&lt;span class="character"&gt;d&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;✎&lt;/span&gt;
&lt;div class="tooltip"&gt;Edit&lt;br /&gt;&lt;span class="character"&gt;✎&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;e&lt;/span&gt;
&lt;div class="tooltip"&gt;Equalizer&lt;br /&gt;&lt;span class="character"&gt;e&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;!&lt;/span&gt;
&lt;div class="tooltip"&gt;Exclamation&lt;br /&gt;&lt;span class="character"&gt;!&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;E&lt;/span&gt;
&lt;div class="tooltip"&gt;Eye&lt;br /&gt;&lt;span class="character"&gt;E&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⚑&lt;/span&gt;
&lt;div class="tooltip"&gt;Flag&lt;br /&gt;&lt;span class="character"&gt;⚑&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;f&lt;/span&gt;
&lt;div class="tooltip"&gt;Fullscreen&lt;br /&gt;&lt;span class="character"&gt;f&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⚙&lt;/span&gt;
&lt;div class="tooltip"&gt;Gear&lt;br /&gt;&lt;span class="character"&gt;⚙&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;g&lt;/span&gt;
&lt;div class="tooltip"&gt;Grid&lt;br /&gt;&lt;span class="character"&gt;g&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;❤&lt;/span&gt;
&lt;div class="tooltip"&gt;Heart&lt;br /&gt;&lt;span class="character"&gt;❤&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⌂&lt;/span&gt;
&lt;div class="tooltip"&gt;Home&lt;br /&gt;&lt;span class="character"&gt;⌂&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;i&lt;/span&gt;
&lt;div class="tooltip"&gt;Info&lt;br /&gt;&lt;span class="character"&gt;i&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;l&lt;/span&gt;
&lt;div class="tooltip"&gt;List&lt;br /&gt;&lt;span class="character"&gt;l&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;L&lt;/span&gt;
&lt;div class="tooltip"&gt;Lock&lt;br /&gt;&lt;span class="character"&gt;L&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⬇&lt;/span&gt;
&lt;div class="tooltip"&gt;Location&lt;br /&gt;&lt;span class="character"&gt;⬇&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;✉&lt;/span&gt;
&lt;div class="tooltip"&gt;Message&lt;br /&gt;&lt;span class="character"&gt;✉&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;m&lt;/span&gt;
&lt;div class="tooltip"&gt;Move&lt;br /&gt;&lt;span class="character"&gt;m&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;♫&lt;/span&gt;
&lt;div class="tooltip"&gt;Music&lt;br /&gt;&lt;span class="character"&gt;♫&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;p&lt;/span&gt;
&lt;div class="tooltip"&gt;Photo&lt;br /&gt;&lt;span class="character"&gt;p&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;▶&lt;/span&gt;
&lt;div class="tooltip"&gt;Play&lt;br /&gt;&lt;span class="character"&gt;▶&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;P&lt;/span&gt;
&lt;div class="tooltip"&gt;Power&lt;br /&gt;&lt;span class="character"&gt;P&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;?&lt;/span&gt;
&lt;div class="tooltip"&gt;Question&lt;br /&gt;&lt;span class="character"&gt;?&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⟲&lt;/span&gt;
&lt;div class="tooltip"&gt;Refresh&lt;br /&gt;&lt;span class="character"&gt;⟲&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;-&lt;/span&gt;
&lt;div class="tooltip"&gt;Remove&lt;br /&gt;&lt;span class="character"&gt;-&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⊝&lt;/span&gt;
&lt;div class="tooltip"&gt;Remove-alt&lt;br /&gt;&lt;span class="character"&gt;⊝&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;r&lt;/span&gt;
&lt;div class="tooltip"&gt;RSS&lt;br /&gt;&lt;span class="character"&gt;r&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;s&lt;/span&gt;
&lt;div class="tooltip"&gt;Share&lt;br /&gt;&lt;span class="character"&gt;s&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;★&lt;/span&gt;
&lt;div class="tooltip"&gt;Star&lt;br /&gt;&lt;span class="character"&gt;★&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;t&lt;/span&gt;
&lt;div class="tooltip"&gt;Tag&lt;br /&gt;&lt;span class="character"&gt;t&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;T&lt;/span&gt;
&lt;div class="tooltip"&gt;Trash&lt;br /&gt;&lt;span class="character"&gt;T&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;u&lt;/span&gt;
&lt;div class="tooltip"&gt;User&lt;br /&gt;&lt;span class="character"&gt;u&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;v&lt;/span&gt;
&lt;div class="tooltip"&gt;Video&lt;br /&gt;&lt;span class="character"&gt;v&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;⚠&lt;/span&gt;
&lt;div class="tooltip"&gt;Warning&lt;br /&gt;&lt;span class="character"&gt;⚠&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span class="icon"&gt;z&lt;/span&gt;
&lt;div class="tooltip"&gt;Zoom&lt;br /&gt;&lt;span class="character"&gt;z&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;/section&gt;
&lt;div&gt;
    有的浏览器居然还不支持&lt;a href="http://www.html5tutorial.info/html5-range.php" target="_blank"&gt;HTML5的range&lt;/a&gt;，所以如果你看到下面是输入框的话，建议你升级浏览器或者是自己输入数字再左键点击页面任何地方…-_-”。Anyway，Icon font确实是很酷的，因为：    &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
			你可以很容易的改变它的大小&lt;/p&gt;
&lt;input type="range" id="font-size-slider" min="6" max="100" value="62"&gt;
		&lt;/li&gt;
&lt;li&gt;
			你可以很容易的改变它的颜色&lt;/p&gt;
&lt;input type="range" class="color-slider" id="color-slider-1" min="0" max="360" value="0"&gt;
&lt;input type="range" class="color-slider" id="color-slider-2" min="0" max="100" value="50"&gt;
&lt;input type="range" class="color-slider" id="color-slider-3" min="0" max="100" value="50"&gt;
		&lt;/li&gt;
&lt;li&gt;
			你甚至可以很容易的改变它的阴影效果&lt;/p&gt;
&lt;input type="range" class="shadow-slider" id="shadow-slider-1" min="0" max="20" value="0"&gt;
&lt;input type="range" class="shadow-slider" id="shadow-slider-2" min="0" max="20" value="0"&gt;
&lt;input type="range" class="shadow-slider" id="shadow-slider-3" min="0" max="20" value="0"&gt;
		&lt;/li&gt;
&lt;li&gt;Icon Font不会有PNG那样的在IE下面不透明的问题&lt;/li&gt;
&lt;li&gt;用了它可以完成任何用图片的icon达到的效果，甚至可以旋转和调整透明度&lt;/li&gt;
&lt;li&gt;只要浏览器支持，你就可以使用&lt;code&gt;text-stroke&lt;/code&gt;或者是&lt;code&gt;background-clip:text;&lt;/code&gt;这种更加复杂的效果了&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;&lt;img src="http://www1.feedsky.com/t1/643255126/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/02/icon-font/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/02/icon-font/feed/</wfw:commentRss><slash:comments>2</slash:comments><description>最近收集了一些Icon Font准备自己的项目里面用（这也是本座因为Stack功能切换回Delicious来管理书签之后第建的第一个Stack）。Icon Font本身看起来和普通的icon没有特别的差别： + Add+ ⊕ Add-alt⊕ a Alerta ← Arrow-left← → Arrow-right→ ↑ Arrow-up↑ ↓ Arrow-down↓ A AttachmentA ↩ Back↩ b Bookmarkb B BubbleB c Cartc C ChartC ✔ Check✔ ⌚ Clock⌚ ☁ Cloud☁ × Delete× ⊗ Delete-alt⊗ d Deniedd ✎ Edit✎ e Equalizere ! Exclamation! E EyeE ⚑ Flag⚑ f Fullscreenf ⚙ Gear⚙ [...]&lt;img src="http://www1.feedsky.com/t1/643255126/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/02/icon-font/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>档案一理</category><category>web design</category><pubDate>Sat, 25 Feb 2012 10:45:29 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/02/icon-font/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=1973</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/02/icon-font/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255126/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/02/icon-font/</feedburner:origLink></item><item><title>Click the squares</title><link>http://feedproxy.google.com/~r/lenciel/~3/lRa7UkNpBpE/</link><content:encoded>&lt;p&gt;放松心情的音乐游戏，玩法非常简单，就是用鼠标点亮（可以再点灭）方块。支持按住左键不放刷亮一片。&lt;br /&gt;
最近被&lt;a href="http://9gag.com" target="_blank"&gt;9GAGer&lt;/a&gt;刷到服务器爆掉，特此镜像备份。&lt;/p&gt;
&lt;p&gt;如果载入较慢说明您网速不行，耐心一些或者试试F5&amp;#8230;&lt;br /&gt;

    &lt;object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="swfobj_0" width="600" height="600" align="center"&gt;
      &lt;param name="movie" value="http://lenciel.cn/wp-content/uploads/matrix.swf" /&gt;
      &lt;param name="align" value="center" /&gt;
      &lt;!--[if !IE]&gt;--&gt;
      &lt;object type="application/x-shockwave-flash" data="http://lenciel.cn/wp-content/uploads/matrix.swf" width="600" height="600" align="center"&gt;
      &lt;!--&lt;![endif]--&gt;
        
      &lt;!--[if !IE]&gt;--&gt;
      &lt;/object&gt;
      &lt;!--&lt;![endif]--&gt;
    &lt;/object&gt;
&lt;br /&gt;
本座音乐盲，只知道尽量迅速的点出比较对称的图案，就还听起来不错。&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255127/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/02/click-the-squares/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/02/click-the-squares/feed/</wfw:commentRss><slash:comments>10</slash:comments><description>放松心情的音乐游戏，玩法非常简单，就是用鼠标点亮（可以再点灭）方块。支持按住左键不放刷亮一片。 最近被9GAGer刷到服务器爆掉，特此镜像备份。 如果载入较慢说明您网速不行，耐心一些或者试试F5&amp;#8230; 本座音乐盲，只知道尽量迅速的点出比较对称的图案，就还听起来不错。&lt;img src="http://www1.feedsky.com/t1/643255127/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/02/click-the-squares/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>game</category><category>随便一扔</category><pubDate>Tue, 07 Feb 2012 12:39:36 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/02/click-the-squares/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=1958</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/02/click-the-squares/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255127/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/02/click-the-squares/</feedburner:origLink></item><item><title>2012</title><link>http://feedproxy.google.com/~r/lenciel/~3/wj1ty6BrM9g/</link><content:encoded>&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2012/01/suburbia_alert_web.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="suburbia_alert_web" border="0" alt="suburbia_alert_web" src="http://lenciel.cn/wp-content/uploads/2012/01/suburbia_alert_web_thumb.jpg" width="704" height="275" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;在读过《&lt;a href="http://book.douban.com/subject/3609132/" target="_blank"&gt;把时间当作朋友&lt;/a&gt;》和&lt;a href="http://matt.might.usesthis.com/" target="_blank"&gt;Matt Might&lt;/a&gt;的文章之后，回首2011就让人觉得莫名慌张起来。按《&lt;a href="http://book.douban.com/subject/3609132/" target="_blank"&gt;把时间当作朋友&lt;/a&gt;》这本书里所说，定计划要以周为单位，通过培养自己对时间的控制力，逐步把计划做到月甚至年这样的跨度。本座自觉还算比较能控制自己，所以打算制作一个基本单位为月的计划，下面的十项活动将穿插在这个计划之中：&lt;/p&gt;
&lt;p&gt;1. 一点新知识    &lt;br /&gt;2. 一砣好身体&amp;#160; &lt;br /&gt;3. 一个新玩具     &lt;br /&gt;4.&amp;#160; 一批新兴趣     &lt;br /&gt;5. 一门新语言     &lt;br /&gt;6. 一款新软件     &lt;br /&gt;7. 一马新项目     &lt;br /&gt;8. 一把新文艺 &lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一点新知识&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;用进废退，数理化史地生音体美忘记了就算了吧。但半路出家的本座，还有很多基础知识也非常单薄。准备了6本不那么理论的书，争取能用2个月一本的龟速精读：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.amazon.com/Code-Language-Computer-Hardware-Software/dp/0735611319/ref=sr_1_1?ie=UTF8&amp;amp;qid=1326115601&amp;amp;sr=8-1" target="_blank"&gt;Code: The Hidden Language of Computer Hardware and Software&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://book.douban.com/subject/4327796/" target="_blank"&gt;Continuous Delivery&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.com/dp/0201752840/?tag=stackoverfl08-20" target="_blank"&gt;Database Design for Mere Mortals&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.com/Event-Processing-Action-Opher-Etzion/dp/1935182218/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1326115894&amp;amp;sr=1-1" target="_blank"&gt;Event Processing in Action&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.com/Art-Concurrency-Monkeys-Parallel-Applications/dp/0596521537/ref=sr_1_1?ie=UTF8&amp;amp;qid=1326115671&amp;amp;sr=8-1" target="_blank"&gt;The Art of Concurrency&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="Designing the Obvious" target="_blank" class="broken_link"&gt;Designing the Obvious&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一砣好身体&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;关注自己的健康状况，保持适当的体育锻炼，既是对自己负责，也是对家人负责。2012年体育锻炼方面的发展目标是除开足球之外，要开拓可以和偶像派互动的项目。下面的四个项目，12个月都可以开展，但是可以根据气候的不同，在四个季度各有偏重：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;跳绳 &lt;/li&gt;
&lt;li&gt;自行车 &lt;/li&gt;
&lt;li&gt;跑步 &lt;/li&gt;
&lt;li&gt;羽毛球 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外，程序员这个职业带来的伤害常常是&lt;a href="http://en.wikipedia.org/wiki/Repetitive_strain_injury" target="_blank"&gt;RSI&lt;/a&gt;。本座一直有比较严重的脖子疼和曾经越来越严重的肩膀和手腕疼。通过了解RSI，保持良好的姿势以及定时起来活动，比较好的缓解了疼痛。但是用电脑有时候是一屁股下去就不好起来的。让人欣喜的，传说中的&lt;a href="http://www.hermanmiller.com/Products/Aeron-Chairs" target="_blank"&gt;Aeron&lt;/a&gt;在中国&lt;a href="http://www.hermanmiller.cn/" target="_blank"&gt;也能&lt;/a&gt;买到了。所以明年还有一个目标：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.hermanmiller.com/Products/Aeron-Chairs" target="_blank"&gt;Aeron&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一个新玩具&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;在回成都之后第一年在E公司主要的玩具是那套收星的玩意儿。原来只要大概800块钱左右的成本(DM500和所有的分路器合路器F头都是在这家淘宝店&lt;a href="http://boattv.taobao.com/?spm=1101_lrm.4-Q8vp.2-91JMq" target="_blank"&gt;买的&lt;/a&gt;），就可以用60CM的锅收&lt;a href="http://www.cnsat.net/134.0.htm" target="_blank"&gt;134&lt;/a&gt;/&lt;a href="http://www.cnsat.net/138.0.htm" target="_blank"&gt;138&lt;/a&gt;/146三颗ku星。&lt;/p&gt;
&lt;p&gt;接下来移籍M公司，主要的玩具似乎变成了Android。但是后来机缘巧合开始接触了各式各样的监控设备。说实在的从前端的IP化的云台枪机，到DVR，到最后的矩阵上墙，里面还是有很多挺有趣的技术。而且像中国这么大一个工地，到处都要装监控，这里面商机也不小。&lt;/p&gt;
&lt;p&gt;明年如果能说动偶像派买个LEGO的&lt;a href="http://mindstorms.lego.com/en-us/Default.aspx" target="_blank"&gt;MindStorm&lt;/a&gt;当然是最好，如果失败，就入手最近红到爆的&lt;a href="http://www.arduino.cc/" target="_blank"&gt;Arduino&lt;/a&gt;，话说本座已经堆了很多这方面的书了都没有真正花时间去看过。可是作为控制系的学生，每次看到它们，都有难以抑制的原始冲动。这种东西，一年玩一个就足够了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mindstorms.lego.com/en-us/Default.aspx" target="_blank"&gt;MindStorm&lt;/a&gt;&amp;#160; or &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.arduino.cc/" target="_blank"&gt;Arduino&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一批新兴趣&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;编程的很多道理你不一定只能在编程中学到，因为人类最先进的学习方法是类比。&lt;/p&gt;
&lt;p&gt;而且，每天坐在电脑前面的老公在老婆和其他亲属心中的仇恨值是很高的。下面是一批本座觉得有可能进化为兴趣爱好并能够得到偶像派的广泛赞许和普遍接受的备选项目。仍然是均分到各个月份，但每个季度有倾斜的加大某项的比重：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;摄影 &lt;/li&gt;
&lt;li&gt;画画 &lt;/li&gt;
&lt;li&gt;写毛笔字 &lt;/li&gt;
&lt;li&gt;厨艺 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一门新语言&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;程序员之所以被认为是个苦逼的职业，很重要的原因就是技术更新换代很快。去年看完《&lt;a href="http://book.douban.com/subject/4768035/" target="_blank"&gt;Seven Languages in Seven Weeks&lt;/a&gt;》之后本座就有计划学一下Haskell和Scala，但是去了一趟杭州拿到冰河翻译的&lt;a href="http://book.douban.com/subject/6859720/" target="_blank"&gt;新书&lt;/a&gt;之后本座把明年的目标换成了下面两个，每个半年：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.apl.jhu.edu/~hall/lisp.html" target="_blank"&gt;Lisp&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.haskell.org/" target="_blank"&gt;Haskell&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一款新软件&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;人的创造力需要反复而大量的的基础知识和实作经验垫底，而基础知识和实作经验往往蕴藏在那些已经被时间验证过的作品里。所以要想拍好电影得看很多好电影，要想写好书得看很多好书，要想写出好软件得用很多好软件。在使用别人的软件时，可以想想如果是自己来写，什么地方做得比它好，什么地方还需要像别人学习。暂定的目标有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ispyconnect.com" target="_blank"&gt;iSpy&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://c9.io/" target="_blank"&gt;Cloud9&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rapidftr.com/" target="_blank"&gt;RAPIDFTR&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openstack.org/" target="_blank"&gt;OpenStack&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一马新项目&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;写软件谋生的好处是不言而喻的，坏处是如果你老是只为了工资奖金写软件，慢慢的你就会感觉到“无趣”。无趣的根源很多，最主要的无非“人家想用xyz，但是只能用zyx”。其实有&lt;a href="https://github.com/" target="_blank"&gt;Github&lt;/a&gt;和&lt;a href="https://bitbucket.org/" target="_blank"&gt;Bitbucket&lt;/a&gt;之后，这些都是借口啊，亲。项目内容暂时保密。&lt;/p&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;一把新文艺&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;还在读研究生的时候(也是J2EE最红火的时候？)，本座发现一件“奇闻“：&lt;a href="http://www.springsource.org/" target="_blank"&gt;Spring&lt;/a&gt;的作者Rod Johnson说之所以自己能写出拨乱反正的《&lt;a href="http://book.douban.com/subject/1426848/" target="_blank"&gt;Expert One-on-one&lt;/a&gt;》和&lt;a href="http://www.springsource.org/" target="_blank"&gt;Spring&lt;/a&gt;，和他学习过的音乐知识是分不开的。Google了一下，原来他除开有计算机学位还是个音乐学博士。&lt;/p&gt;
&lt;p&gt;之后稍微留心就发现，这是一个普遍的现象。比如那个写微积分教材赚的钱就可以建2400w刀豪宅的音乐家&lt;a href="http://www.thestar.com/news/article/933017--the-house-that-math-built" target="_blank"&gt;James Stewart&lt;/a&gt;，再比如2011年最被关注的去世者&lt;a href="http://en.wikipedia.org/wiki/Steve_Jobs" target="_blank"&gt;Steve Jobs&lt;/a&gt;。有点儿文艺细胞，能从人性的角度思考，做出的产品往往比纯粹的工程产品要打动人心。&lt;/p&gt;
&lt;p&gt;本座挺佩服自己能找出这么一个伟大的理由，得以在新的一年里继续毫无节制的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;看电影 &lt;/li&gt;
&lt;li&gt;读小说 &lt;/li&gt;
&lt;li&gt;听音乐 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;p&gt;要顺利贯彻执行计划，总得有个考核标准。打算今后多写一点儿blog记录在案，不然也对不起本座A给酋长的银子啊：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2012/01/QQ20120110163426.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="QQ截图20120110163426" border="0" alt="QQ截图20120110163426" src="http://lenciel.cn/wp-content/uploads/2012/01/QQ20120110163426_thumb.png" width="260" height="101" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255128/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/01/plan-for-2012/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2012/01/plan-for-2012/feed/</wfw:commentRss><slash:comments>7</slash:comments><description>在读过《把时间当作朋友》和Matt Might的文章之后，回首2011就让人觉得莫名慌张起来。按《把时间当作朋友》这本书里所说，定计划要以周为单位，通过培养自己对时间的控制力，逐步把计划做到月甚至年这样的跨度。本座自觉还算比较能控制自己，所以打算制作一个基本单位为月的计划，下面的十项活动将穿插在这个计划之中： 1. 一点新知识 2. 一砣好身体&amp;#160; 3. 一个新玩具 4.&amp;#160; 一批新兴趣 5. 一门新语言 6. 一款新软件 7. 一马新项目 8. 一把新文艺 一点新知识 用进废退，数理化史地生音体美忘记了就算了吧。但半路出家的本座，还有很多基础知识也非常单薄。准备了6本不那么理论的书，争取能用2个月一本的龟速精读： Code: The Hidden Language of Computer Hardware and Software Continuous Delivery Database Design for Mere Mortals Event Processing in Action The Art of Concurrency Designing the Obvious &amp;#160; 一砣好身体 关注自己的健康状况，保持适当的体育锻炼，既是对自己负责，也是对家人负责。2012年体育锻炼方面的发展目标是除开足球之外，要开拓可以和偶像派互动的项目。下面的四个项目，12个月都可以开展，但是可以根据气候的不同，在四个季度各有偏重： 跳绳 自行车 跑步 羽毛球 另外，程序员这个职业带来的伤害常常是RSI。本座一直有比较严重的脖子疼和曾经越来越严重的肩膀和手腕疼。通过了解RSI，保持良好的姿势以及定时起来活动，比较好的缓解了疼痛。但是用电脑有时候是一屁股下去就不好起来的。让人欣喜的，传说中的Aeron在中国也能买到了。所以明年还有一个目标： [...]&lt;img src="http://www1.feedsky.com/t1/643255128/lenciel/feedsky/s.gif?r=http://lenciel.cn/2012/01/plan-for-2012/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>仰天一笑</category><category>plan</category><pubDate>Tue, 10 Jan 2012 17:25:33 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2012/01/plan-for-2012/#comments</comments><guid isPermaLink="false">http://lenciel.cn/?p=1954</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2012/01/plan-for-2012/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255128/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2012/01/plan-for-2012/</feedburner:origLink></item><item><title>老无所依</title><link>http://feedproxy.google.com/~r/lenciel/~3/DFmkiFTbQ68/</link><content:encoded>&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0313.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_0313" border="0" alt="IMG_0313" src="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0313_thumb.jpg" width="604" height="354" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;国庆回了一趟银厂沟白水河。出发的那天天气并不好，可是对爸妈而言，去看看那个安放了自己青春的地方，已经计划过太多次而不能成行。所以犹豫了一下，就决定还是要去。&lt;/p&gt;
&lt;p&gt;车一开进山区，因为属于汶川大地震里山崩地裂的龙门山山脉，那场灾难留下的痕迹依然随处可见。然而地貌上的变化却并不是爸妈最关注：一路上他们不断提起的是故人的名字，以及自己和他们之间的种种旧事。有的时候我爸会往路边一指说，“那不是黄村吗？以前你妈下乡在那里的时候，我骑车来看过她。”有的时候我妈又会指着另一个地方说，“那个谁谁谁，就是在这里被掉下来的房梁打死了，太可惜了。”&lt;/p&gt;
&lt;p&gt;而白水河对于我，因为是十岁之前生活的地方，本来就没有多少刻骨铭心的记忆。加上我和Konthiga读过的小学和学校后面那条曾经清澈而壮阔的白水河，在上次回去的时候就已经面目全非了，于是唯一怀着兴趣的就只剩据说在地震里面一栋都没有倒的蛇纹矿家属区，也就是我们当年长大的地方。坐在我旁边的偶像派，在我们一家人兴致勃勃的指着窗外大呼小叫时，则多少显得有些百无聊赖。&lt;/p&gt;
&lt;p&gt;后来事情的发展让人觉得略感尴尬。走到“鬼招手”（银厂沟一个以险峻著称的地段）的时候，前面的山路突然淹没在浓雾之中，我们只好调头，放弃了继续进沟的打算。接下来在大宝镇上兜了两圈，我们才凭借着整条街上几乎是唯一没有被拆除的新华书店，定位到了我们原来的住处：居然已经是一片平地。&lt;/p&gt;
&lt;p&gt;回到家里，我突然有些不死心的想把记忆里的白水河挖出来，就去翻家里的老照片。&lt;/p&gt;
&lt;p&gt;首先让我觉得特别温暖的是装老照片的这个信封。这是外公写给我妈的，不知道当年那封信具体写得是啥。在这根本不用写信甚至不用写字的时代生活久了，这样的物件总给人一种特别的质感。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0366_1.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="IMG_0366_1" border="0" alt="IMG_0366_1" src="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0366_1_thumb.png" width="604" height="434" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;我还找到了几张Konthiga和我都还挺萌的时候的照片。这个阶段我们的衣服全是老爸用缝纫机做的，看着都是一段段特别的回忆。另外从红领巾出现的频率来看，除了伟大的六一儿童节，我们一直对照相这事情兴趣不大。&lt;/p&gt;
&lt;p&gt;&lt;span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: medium tahoma; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0172.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_0172" border="0" alt="IMG_0172" src="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0172_thumb.jpg" width="204" height="275" /&gt;&lt;/a&gt; &lt;a href="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0168.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_0168" border="0" alt="IMG_0168" src="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0168_thumb.jpg" width="204" height="285" /&gt;&lt;/a&gt; &lt;a href="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0200.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_0200" border="0" alt="IMG_0200" src="http://lenciel.cn/wp-content/uploads/2011/11/IMG_0200_thumb.jpg" width="204" height="288" /&gt;&lt;/a&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;看这些照片的时候，最大的怀念是以前生活在青山绿水的白水河时，我们一家人那轻松自在的身段。在我们匆忙长大的这二十来年，中国也一直在匆忙的变化着。我们的文艺工作者在世纪之交做过很多牛逼哄哄的选题，什么《激荡三十年》，什么《大国崛起》，妄图把这个剧变的时代描绘成一代人怀着同样的目标，努力奋斗让中国崛起的时代。&lt;/p&gt;
&lt;p&gt;而实际上，绝大多数家庭就和我们家一样，我们并没有主动的参与到那些变化里面去。很多人虽然听组织安排上山下乡或者援建支边，但和全国志士要行动起来抛头颅洒热血的革命年代不同，大多数人的生活目标与生存焦虑既无关这个社会，也无关这个国家，都是些极度自我的事情。但这个国家变化得如此剧烈，昨天还有效的经验，明天就可能完全完蛋。所以更多的时候，毫无信仰的中国人无力的忍受着生活剧烈的摇摆，随波逐流的同时，常常感到心灵上莫大的空虚和痛苦。&lt;/p&gt;
&lt;p&gt;所以，在过去我曾经为父母和我们生活在不同的世界，或者是他们的婚姻变得危机四伏而苦恼不已。可是等我到了一定年纪就发现原来他们那代人中并没有多少真正快乐的夫妻：他们大多数人，在生活中不断的否定着自己信仰过的东西。要人们在这种奇特的生活环境中保持感情的稳定，也许的确是要求高了一些。&lt;/p&gt;
&lt;p&gt;相比之下，我们这代人当然要幸运一些。虽然如果统计一下，应该没有几个人自己长大的老房子还没有被拆。但至少我们留下了不少照片，从感觉上，已经不是那么老无所依。&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255129/lenciel/feedsky/s.gif?r=http://lenciel.cn/2011/11/long-live-old-times/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2011/11/long-live-old-times/feed/</wfw:commentRss><slash:comments>18</slash:comments><description>国庆回了一趟银厂沟白水河。出发的那天天气并不好，可是对爸妈而言，去看看那个安放了自己青春的地方，已经计划过太多次而不能成行。所以犹豫了一下，就决定还是要去。 车一开进山区，因为属于汶川大地震里山崩地裂的龙门山山脉，那场灾难留下的痕迹依然随处可见。然而地貌上的变化却并不是爸妈最关注：一路上他们不断提起的是故人的名字，以及自己和他们之间的种种旧事。有的时候我爸会往路边一指说，“那不是黄村吗？以前你妈下乡在那里的时候，我骑车来看过她。”有的时候我妈又会指着另一个地方说，“那个谁谁谁，就是在这里被掉下来的房梁打死了，太可惜了。” 而白水河对于我，因为是十岁之前生活的地方，本来就没有多少刻骨铭心的记忆。加上我和Konthiga读过的小学和学校后面那条曾经清澈而壮阔的白水河，在上次回去的时候就已经面目全非了，于是唯一怀着兴趣的就只剩据说在地震里面一栋都没有倒的蛇纹矿家属区，也就是我们当年长大的地方。坐在我旁边的偶像派，在我们一家人兴致勃勃的指着窗外大呼小叫时，则多少显得有些百无聊赖。 后来事情的发展让人觉得略感尴尬。走到“鬼招手”（银厂沟一个以险峻著称的地段）的时候，前面的山路突然淹没在浓雾之中，我们只好调头，放弃了继续进沟的打算。接下来在大宝镇上兜了两圈，我们才凭借着整条街上几乎是唯一没有被拆除的新华书店，定位到了我们原来的住处：居然已经是一片平地。 回到家里，我突然有些不死心的想把记忆里的白水河挖出来，就去翻家里的老照片。 首先让我觉得特别温暖的是装老照片的这个信封。这是外公写给我妈的，不知道当年那封信具体写得是啥。在这根本不用写信甚至不用写字的时代生活久了，这样的物件总给人一种特别的质感。 我还找到了几张Konthiga和我都还挺萌的时候的照片。这个阶段我们的衣服全是老爸用缝纫机做的，看着都是一段段特别的回忆。另外从红领巾出现的频率来看，除了伟大的六一儿童节，我们一直对照相这事情兴趣不大。 看这些照片的时候，最大的怀念是以前生活在青山绿水的白水河时，我们一家人那轻松自在的身段。在我们匆忙长大的这二十来年，中国也一直在匆忙的变化着。我们的文艺工作者在世纪之交做过很多牛逼哄哄的选题，什么《激荡三十年》，什么《大国崛起》，妄图把这个剧变的时代描绘成一代人怀着同样的目标，努力奋斗让中国崛起的时代。 而实际上，绝大多数家庭就和我们家一样，我们并没有主动的参与到那些变化里面去。很多人虽然听组织安排上山下乡或者援建支边，但和全国志士要行动起来抛头颅洒热血的革命年代不同，大多数人的生活目标与生存焦虑既无关这个社会，也无关这个国家，都是些极度自我的事情。但这个国家变化得如此剧烈，昨天还有效的经验，明天就可能完全完蛋。所以更多的时候，毫无信仰的中国人无力的忍受着生活剧烈的摇摆，随波逐流的同时，常常感到心灵上莫大的空虚和痛苦。 所以，在过去我曾经为父母和我们生活在不同的世界，或者是他们的婚姻变得危机四伏而苦恼不已。可是等我到了一定年纪就发现原来他们那代人中并没有多少真正快乐的夫妻：他们大多数人，在生活中不断的否定着自己信仰过的东西。要人们在这种奇特的生活环境中保持感情的稳定，也许的确是要求高了一些。 相比之下，我们这代人当然要幸运一些。虽然如果统计一下，应该没有几个人自己长大的老房子还没有被拆。但至少我们留下了不少照片，从感觉上，已经不是那么老无所依。&lt;img src="http://www1.feedsky.com/t1/643255129/lenciel/feedsky/s.gif?r=http://lenciel.cn/2011/11/long-live-old-times/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>弹指一挥</category><category>time</category><pubDate>Sun, 20 Nov 2011 21:46:33 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2011/11/long-live-old-times/#comments</comments><guid isPermaLink="false">http://lenciel.cn/2011/11/long-live-old-times/</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2011/11/long-live-old-times/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255129/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2011/11/long-live-old-times/</feedburner:origLink></item><item><title>width:100%</title><link>http://feedproxy.google.com/~r/lenciel/~3/mwDvy_vaURM/</link><content:encoded>&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2011/09/width100css.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="width-100-css" border="0" alt="width-100-css" align="left" src="http://lenciel.cn/wp-content/uploads/2011/09/width100css_thumb.jpg" width="213" height="253" /&gt;&lt;/a&gt; 这似乎是CSS里面最简单的一个概念：如果你希望一个block-level的元素填满整个父容器的所有空白，只需要为这个元素声明&lt;font color="#0080ff"&gt;width:100%&lt;/font&gt;这个属性就可以了。&lt;/p&gt;
&lt;p&gt;但从个人经验和搜索结果看，大概很多CSS使用者都有过加上这个属性后挠头不已的惨痛回忆。最后很多人不得不经过反复试验后重新转回使用绝对值的长和宽。&lt;/p&gt;
&lt;p&gt;的确，百分比在CSS里的真实作用，就像偶像派的苦瓜炒蛋，是属于“看起来简单，弄起来挺难”的东西。&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;&lt;br /&gt;
&lt;h4&gt;其实Blocks不需要指定100%&lt;/h4&gt;
&lt;p&gt; &lt;/strong&gt;
&lt;p&gt;大多数专业的Web开发者都清楚，block-level的元素(如div, p, ul等)和inline的元素两者的区别就在于默认情况下，block元素的宽度就会取填满父容器的宽度(减去自己的margin或者父容器的padding)。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2011/09/blockelementnoneed.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="block-element-noneed" border="0" alt="block-element-noneed" src="http://lenciel.cn/wp-content/uploads/2011/09/blockelementnoneed_thumb.jpg" width="600" height="329" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;这知识虽然初级，理解这点对我们明白百分比的实际作用很有帮助。&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;&lt;br /&gt;
&lt;h4&gt;真实的含义&lt;/h4&gt;
&lt;p&gt; &lt;/strong&gt;
&lt;p&gt;如果你在CSS中给一个元素x%的宽度，其实就是定义：“把这个元素所占的区域扩成它父容器的绝对宽度的x%，当然，必须它父容器有一个绝对宽度啊，亲。”比如你的元素放在一个400px宽度的容器里面，然后它的宽度定成了100%，那么它在保证自己被渲染成400px宽度之后，还是会遵守自己被定义margin/padding/border的设置，所以最好出来的效果很可能就是下图那悲催样：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lenciel.cn/wp-content/uploads/2011/09/childequal.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="child-equal" border="0" alt="child-equal" src="http://lenciel.cn/wp-content/uploads/2011/09/childequal_thumb.jpg" width="600" height="545" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; &lt;strong&gt;&lt;br /&gt;
&lt;h4&gt;Height(在所有的浏览器)也一样&lt;/h4&gt;
&lt;p&gt; &lt;/strong&gt;
&lt;p&gt;是的，这是CSS比较桶妈的地方：如果你的父容器没有一个显示声明的绝对值高度，那么你用百分比来定义它的高度希望它充满父容器是不行的。Height和Width的唯一区别是对于block-level的element而言，不会自动去填满父容器，也就是说height:100%是不能省略的。&lt;/p&gt;
&lt;p&gt;当然，百分号的行为也是CSS里面难得不桶妈的地方：所有的浏览器对百分比的渲染都是一致的。&lt;/p&gt;&lt;img src="http://www1.feedsky.com/t1/643255130/lenciel/feedsky/s.gif?r=http://lenciel.cn/2011/09/width_with_percentage_in_css/" border="0" height="0" width="0" style="position:absolute" /&gt;</content:encoded><wfw:commentRss>http://lenciel.cn/2011/09/width_with_percentage_in_css/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>这似乎是CSS里面最简单的一个概念：如果你希望一个block-level的元素填满整个父容器的所有空白，只需要为这个元素声明width:100%这个属性就可以了。 但从个人经验和搜索结果看，大概很多CSS使用者都有过加上这个属性后挠头不已的惨痛回忆。最后很多人不得不经过反复试验后重新转回使用绝对值的长和宽。 的确，百分比在CSS里的真实作用，就像偶像派的苦瓜炒蛋，是属于“看起来简单，弄起来挺难”的东西。 其实Blocks不需要指定100% 大多数专业的Web开发者都清楚，block-level的元素(如div, p, ul等)和inline的元素两者的区别就在于默认情况下，block元素的宽度就会取填满父容器的宽度(减去自己的margin或者父容器的padding)。 这知识虽然初级，理解这点对我们明白百分比的实际作用很有帮助。 真实的含义 如果你在CSS中给一个元素x%的宽度，其实就是定义：“把这个元素所占的区域扩成它父容器的绝对宽度的x%，当然，必须它父容器有一个绝对宽度啊，亲。”比如你的元素放在一个400px宽度的容器里面，然后它的宽度定成了100%，那么它在保证自己被渲染成400px宽度之后，还是会遵守自己被定义margin/padding/border的设置，所以最好出来的效果很可能就是下图那悲催样： Height(在所有的浏览器)也一样 是的，这是CSS比较桶妈的地方：如果你的父容器没有一个显示声明的绝对值高度，那么你用百分比来定义它的高度希望它充满父容器是不行的。Height和Width的唯一区别是对于block-level的element而言，不会自动去填满父容器，也就是说height:100%是不能省略的。 当然，百分号的行为也是CSS里面难得不桶妈的地方：所有的浏览器对百分比的渲染都是一致的。&lt;img src="http://www1.feedsky.com/t1/643255130/lenciel/feedsky/s.gif?r=http://lenciel.cn/2011/09/width_with_percentage_in_css/" border="0" height="0" width="0" style="position:absolute" /&gt;</description><category>随便一扔</category><category>css</category><category>web dev</category><pubDate>Thu, 22 Sep 2011 13:32:28 +0800</pubDate><author>lenciel</author><comments>http://lenciel.cn/2011/09/width_with_percentage_in_css/#comments</comments><guid isPermaLink="false">http://lenciel.cn/2011/09/width100/</guid><dc:creator>lenciel</dc:creator><fs:srclink>http://lenciel.cn/2011/09/width_with_percentage_in_css/</fs:srclink><fs:srcfeed>http://lenciel.cn/feed</fs:srcfeed><fs:itemid>feedsky/lenciel/~7028840/643255130/1233190</fs:itemid><feedburner:origLink>http://lenciel.cn/2011/09/width_with_percentage_in_css/</feedburner:origLink></item></channel></rss>

