<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>caimaoy's blog</title><link href="http://caimaoy.github.io/" rel="alternate"></link><link href="http://caimaoy.github.io/feeds/all.atom.xml" rel="self"></link><id>http://caimaoy.github.io/</id><updated>2015-11-05T22:53:00+08:00</updated><entry><title>python list implementation</title><link href="http://caimaoy.github.io/python-list-implementation.html" rel="alternate"></link><updated>2015-10-16T17:47:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-10-16:python-list-implementation.html</id><summary type="html">&lt;h1&gt;Python list implementation&lt;/h1&gt;
&lt;h1&gt;深入 Python 列表的内部实现&lt;/h1&gt;
&lt;p&gt;This post describes the CPython implementation of the list object. CPython is the most used Python implementation.  &lt;/p&gt;
&lt;p&gt;Lists in Python are powerful and it is interesting to see how they are implemented internally.  &lt;/p&gt;
&lt;p&gt;Following is a simple Python script appending some integers to a list and printing them.  &lt;/p&gt;
&lt;p&gt;Cpython 是 Python 最为常见的实现。 Python 中的列表非常强大，本文介绍了列表在 CPython 内部是如何实现的，一定非常有趣。  &lt;/p&gt;
&lt;p&gt;下面是一段 Python 脚本，在列表中添加几个整数，然后打印列表。  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; l = []
&amp;gt;&amp;gt;&amp;gt; l.append(1)
&amp;gt;&amp;gt;&amp;gt; l.append(2)
&amp;gt;&amp;gt;&amp;gt; l.append(3)
&amp;gt;&amp;gt;&amp;gt; l
[1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; for e in l:
...   print e
...
1
2
3
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see, lists are iterable.  &lt;/p&gt;
&lt;p&gt;可以发现，列表是一个迭代器。&lt;/p&gt;
&lt;h2&gt;List object C structure&lt;/h2&gt;
&lt;h2&gt;列表对象的 C 语言结构体&lt;/h2&gt;
&lt;p&gt;A list object in CPython is represented by the following C structure. ob_item is a list of pointers to the list elements. allocated is the number of slots allocated in memory.  &lt;/p&gt;
&lt;p&gt;Cpython 中的列表实现类似于下面的 C 结构体。ob_item 是指向列表对象的指针数组。allocated 是申请内存的槽的个数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;typedef struct {
    PyObject_VAR_HEAD
    PyObject **ob_item;
    Py_ssize_t allocated;
} PyListObject;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;List initialization&lt;/h2&gt;
&lt;h2&gt;列表初始化&lt;/h2&gt;
&lt;p&gt;Let’s look at what happens when we initialize an empty list. e.g. l = [].  &lt;/p&gt;
&lt;p&gt;看看列表初始化的时候发生了什么，例如：l = []。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;PyListNew&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;nbytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;allocate&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;
    &lt;span class="n"&gt;allocate&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;pointers&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ob_item&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;nbytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;clear&lt;/span&gt; &lt;span class="n"&gt;ob_item&lt;/span&gt;
    &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;allocated&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;slots&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It is important to notice the difference between allocated slots and the size of the list. The size of a list is the same as len(l). The number of allocated slots is what has been allocated in memory. Often, you will see that allocated can be greater than size. This is to avoid needing calling realloc each time a new elements is appended to the list. We will see more about that later.  &lt;/p&gt;
&lt;p&gt;要分清列表大小和分配的槽大小，这很重要。列表的大小和 len(l) 的大小相同。分配槽的大小是指已经在内存中已经分配了的槽空间数。通常分配的槽的大小要大于列表大小，这是为了避免每次列表添加元素的时候都调用分配内存的函数。下面会具体介绍。&lt;/p&gt;
&lt;h2&gt;Append&lt;/h2&gt;
&lt;h2&gt;Append 操作&lt;/h2&gt;
&lt;p&gt;We append an integer to the list: l.append(1). What happens? The internal C function app1() is called:  &lt;/p&gt;
&lt;p&gt;向列表添加一个整数：l.append(1) 时发生了什么？调用了底层的 C 函数 app1()。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt;
&lt;span class="n"&gt;app1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;
    &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;list_resize&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;resize&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Let’s look at list_resize(). It over-allocates memory to avoid calling list_resize too many time. The growth pattern of the list is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, …  &lt;/p&gt;
&lt;p&gt;下面是 list_resize() 函数。它会多申请一些内存，避免频繁调用 list_resize() 函数。列表的增长系列为：0，4，8，16，25，35，46，58，72，88……&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt;
&lt;span class="n"&gt;list_resize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;new_allocated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newsize&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newsize&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;new_allocated&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;newsize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="n"&gt;resize&lt;/span&gt; &lt;span class="n"&gt;ob_item&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;pointers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;new_allocated&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;4 slots are now allocated to contain elements and the first one is the integer 1. You can see on the following diagram that l[0] points to the integer object that we just appended. The dashed squares represent the slots allocated but not used yet.  &lt;/p&gt;
&lt;p&gt;现在分配了 4 个用来装列表元素的槽空间，并且第一个空间中为整数 1。如下图显示 l[0] 指向我们新添加的整数对象。虚线的方框表示已经分配但没有使用的槽空间。&lt;/p&gt;
&lt;p&gt;Append operation amortized complexity is O(1).  &lt;/p&gt;
&lt;p&gt;列表追加元素操作的平均复杂度为 O(1)。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://ww4.sinaimg.cn/large/61203d71gw1ex3418lleoj204h05twef.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;We continue by adding one more element: l.append(2). list_resize is called with n+1 = 2 but because the allocated size is 4, there is no need to allocate more memory. Same thing happens when we add 2 more integers: l.append(3), l.append(4). The following diagram shows what we have so far.  &lt;/p&gt;
&lt;p&gt;继续添加新的元素：l.append(2)。调用 list_resize 函数，参数为 n+1 = 2， 但是因为已经申请了 4 个槽空间，所以不需要再申请内存空间。再添加两个整数的情况也是一样的：l.append(2)，l.append(2)。下图显示了我们现在的情况。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://ww3.sinaimg.cn/mw690/61203d71gw1ex3418cf9uj204h07gjrf.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;Insert&lt;/h2&gt;
&lt;h2&gt;Insert 操作&lt;/h2&gt;
&lt;p&gt;Let’s insert a new integer (5) at position 1: l.insert(1,5) and look at what happens internally. ins1() is called:  &lt;/p&gt;
&lt;p&gt;在列表偏移量 1 的位置插入新元素，整数 5：l.insert(1,5)，内部调用ins1() 函数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt;
&lt;span class="n"&gt;ins1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;resize&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;slots&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;allocated&lt;/span&gt;
    &lt;span class="n"&gt;starting&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="n"&gt;shift&lt;/span&gt; &lt;span class="k"&gt;each&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
    &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;img alt="" src="http://ww4.sinaimg.cn/mw690/61203d71gw1ex34198im9j20ht0ad0tn.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The dashed squares represent the slots allocated but not used yet. Here, 8 slots are allocated but the size or length of the list is only 5.  &lt;/p&gt;
&lt;p&gt;虚线的方框依旧表示已经分配但没有使用的槽空间。现在分配了 8 个槽空间，但是列表的大小却只是 5。&lt;/p&gt;
&lt;p&gt;Insert operation complexity is O(n).  &lt;/p&gt;
&lt;p&gt;列表插入操作的平均复杂度为 O(n)。&lt;/p&gt;
&lt;h2&gt;Pop&lt;/h2&gt;
&lt;h2&gt;Pop 操作&lt;/h2&gt;
&lt;p&gt;When you pop the last element: l.pop(), listpop() is called. list_resize is called inside listpop() and if the new size is less than half of the allocated size then the list is shrunk.  &lt;/p&gt;
&lt;p&gt;弹出列表最后一个元素：调用 listpop() 函数。在 listpop() 函数中会调用 list_resize 函数，如果弹出元素后列表的大小小于分配的槽空间数的一半，将会缩减列表的大小。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;popped&lt;/span&gt;
&lt;span class="n"&gt;listpop&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="n"&gt;resize&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;less&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;shrinkage&lt;/span&gt;
    &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Pop operation complexity is O(1).&lt;br /&gt;
列表 pop 操作的平均复杂度为 O(1)。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://ww2.sinaimg.cn/mw690/61203d71gw1ex3419wrvaj20fg0adwf9.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;You can observe that slot 4 still points to the integer but the important thing is the size of the list which is now 4.  &lt;/p&gt;
&lt;p&gt;可以看到 pop 操作后槽空间 4 依然指向原先的整数对象，但是最为关键的是现在列表的大小已经变为 4。  &lt;/p&gt;
&lt;p&gt;Let’s pop one more element. In list_resize(), size – 1 = 4 – 1 = 3 is less than half of the allocated slots so the list is shrunk to 6 slots and the new size of the list is now 3.  &lt;/p&gt;
&lt;p&gt;继续 pop 一个元素。在 list_resize() 函数中，size – 1 = 4 – 1 = 3 已经小于所分配的槽空间大小的一半，所以缩减分配的槽空间为 6，同时现在列表的大小为 3。  &lt;/p&gt;
&lt;p&gt;You can observe that slot 3 and 4 still point to some integers but the important thing is the size of the list which is now 3.  &lt;/p&gt;
&lt;p&gt;可以看到槽空间 3 和 4 依然指向原先的整数，但是现在列表的大小已经变为 3。  &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://ww1.sinaimg.cn/mw690/61203d71gw1ex3419ln7uj20fc0aa3zb.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;Remove&lt;/h2&gt;
&lt;h2&gt;Remove 操作&lt;/h2&gt;
&lt;p&gt;Python list object has a method to remove a specific element: l.remove(5). listremove() is called.  &lt;/p&gt;
&lt;p&gt;Python 的列表对象有个方法，删除指定的元素： l.remove(5)。底层调用 listremove() 函数。  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt;
&lt;span class="n"&gt;listremove&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="n"&gt;through&lt;/span&gt; &lt;span class="k"&gt;each&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;correct&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s slot and element&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;none&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To slice the list and remove the element, list_ass_slice() is called and it is interesting to see how it works. Here, low offset is 1 and high offset is 2 as we are removing the element 5 at position 1.  &lt;/p&gt;
&lt;p&gt;为了做列表的切片并且删除元素，调用了 list_ass_slice() 函数，它的实现方法比较有趣。我们在删除列表位置 1 的元素 5 的时候，低位的偏移量为 1 同时高位的偏移量为 2.  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;
&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="n"&gt;list_ass_slice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;recycle&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;dereference&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;
    &lt;span class="n"&gt;shift&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;resize&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;slots&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Remove operation complexity is O(n).  &lt;/p&gt;
&lt;p&gt;列表 remove 操作的复杂度为 O(n)。  &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://ww3.sinaimg.cn/mw690/61203d71gw1ex341ajn3fj20c9096wf2.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;文章翻译自：&lt;a href="http://www.laurentluce.com/posts/python-list-implementation/"&gt;http://www.laurentluce.com/posts/python-list-implementation/&lt;/a&gt;&lt;/p&gt;</summary><category term="python"></category><category term="list"></category><category term="implementation"></category></entry><entry><title>修复pelican 3.6 后没有标签云</title><link href="http://caimaoy.github.io/pelican-tag-cloud.html" rel="alternate"></link><updated>2015-09-27T16:55:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-09-27:pelican-tag-cloud.html</id><summary type="html">&lt;h3&gt;提问：我的标签咋不见了？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;换了新的电脑 pelican 还是要先安装&lt;/li&gt;
&lt;li&gt;使用了如下的命令：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install pelican
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;好像一切正常，拉取一下仓库，make 一下，发现标签云没有了&lt;/li&gt;
&lt;li&gt;为什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;回答：pelican 版本升级，标签云 tag_cloud 被移除了&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;看看官网的 faq 吧—— &lt;a href="http://docs.getpelican.com/en/3.6.3/faq.html?#my-tag-cloud-is-missing-broken-since-i-upgraded-pelican"&gt;http://docs.getpelican.com/en/3.6.3/faq.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;My tag-cloud is missing/broken since I upgraded Pelican
In an ongoing effort to steamline Pelican, tag_cloud generation has been moved out of the pelican core and into a separate plugin. See the Plugins documentation further information about the Pelican plugin system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;解决：添加插件&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/getpelican/pelican-plugins"&gt;pelican 的插件库地址&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;拉取仓库下来，修改 pelicanconf.py 或者 publishconf.py 文件&lt;/li&gt;
&lt;li&gt;添加类似于如下的配置&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;# 插件路径
PLUGIN_PATHS = [&amp;#39;pelican-plugins&amp;#39;]
# 添加插件
PLUGINS = [&amp;#39;tag_cloud&amp;#39;,]

# tag_cloud 配置(自己个性配置)
DISPLAY_TAGS_INLINE = True
DISPLAY_TAGS_ON_SIDEBAR = True
TAG_CLOUD_STEPS = 4
&lt;/pre&gt;&lt;/div&gt;</summary><category term="python pelican"></category></entry><entry><title>nginx + gunicorn + supervisior + flask 部署 python web</title><link href="http://caimaoy.github.io/deploy-python-web.html" rel="alternate"></link><updated>2015-09-13T10:00:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-09-13:deploy-python-web.html</id><summary type="html">&lt;h1&gt;简介&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;最近离职休假，在家研究 python 的 web 框架&lt;/li&gt;
&lt;li&gt;本来是要来 tornado 的，但是因为 Falsk 文档更为齐全，并且更易上手，所以先来了flask&lt;/li&gt;
&lt;li&gt;做了一个小 web 之后就想发布，看了一下官方文档说了 Heroku 云服务和其他的 VPS，于是上Heroku 上面去折腾了一番&lt;/li&gt;
&lt;li&gt;除了 git 和 Heroku 自己的东西，中间在启动的时候有如下代码：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gunicorn&lt;/span&gt; &lt;span class="n"&gt;gettingstarted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wsgi&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;gunicorn 是什么？&lt;/li&gt;
&lt;li&gt;继续 google 发现了一套比较通用的部署 python web app 的解决方案&lt;/li&gt;
&lt;li&gt;nginx + gunicorn + supervisior + flask 来吧在本地折腾一番吧&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;大体介绍&lt;/h1&gt;
&lt;h2&gt;创建一个项目&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mkdir myproject
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;创建 python 虚拟环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;virtualenv is a tool to create isolated Python environments.&lt;/li&gt;
&lt;li&gt;不同项目完全隔离的 python 虚拟环境&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mkdir myproject
cd myproject
virtualenv venv
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;使用 venv 环境&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;source venv/bin/activate
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;安装 python web 框架 flask&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions. And before you ask: It's BSD licensed!&lt;/li&gt;
&lt;li&gt;使用 pip 安装 flask&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install flask
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;mpapp.py 文件&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;启动flask&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;python myapp.py
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;正常情况下可以在浏览器中访问 &lt;a href="http://127.0.0.1:5000"&gt;http://127.0.0.1:5000&lt;/a&gt; 查看到 hello world&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;使用 gunicorn 部署 python web&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model ported from Ruby's Unicorn project. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy.&lt;/li&gt;
&lt;li&gt;安装 gunicorn&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install gunicorn
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;pip 是用于 python 的包管理工具&lt;/li&gt;
&lt;li&gt;我们现在在这个项目中又安装了新的 python 库，所以我们需要记录在 requirements.txt 文件中&lt;/li&gt;
&lt;li&gt;这样方便方便别人部署&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip freeze &amp;gt; requirements.txt
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;当我们安装好 gunicorn 之后，需要用 gunicorn 启动 flask&lt;/li&gt;
&lt;li&gt;注意 flask 里面的name 里面的代码启动了 app.run()&lt;/li&gt;
&lt;li&gt;这个含义是用 flask 自带的服务器启动 app&lt;/li&gt;
&lt;li&gt;这里我们使用了 gunicorn，myapp.py 就等同于一个库文件，被 gunicorn 调用&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;gunicron -w4 -b0.0.0.0:8000 myapp:app
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;此时，我们需要用 8000 的端口进行访问，原先的5000 并没有启用&lt;/li&gt;
&lt;li&gt;其中 gunicorn 的部署中，-w 表示开启多少个 worker&lt;/li&gt;
&lt;li&gt;b 表示 gunicorn 开发的访问地址&lt;/li&gt;
&lt;li&gt;想要结束 gunicorn 只需执行 pkill gunicorn&lt;/li&gt;
&lt;li&gt;有时候还的 ps 找到 pid 进程号才能 kill&lt;/li&gt;
&lt;li&gt;可是这对于一个开发来说，太过于繁琐，因此出现了另外一个神器---supervisor&lt;/li&gt;
&lt;li&gt;一个专门用来管理进程的工具，还可以管理系统的工具进程&lt;/li&gt;
&lt;li&gt;到此 python web 应用 可以正常使用&lt;/li&gt;
&lt;li&gt;之后的进程管理和 nginx 部署还够写很多，之后再见&lt;/li&gt;
&lt;/ul&gt;</summary><category term="python"></category><category term="web"></category><category term="nginx"></category><category term="gunicorn"></category><category term="supervisior"></category><category term="flask"></category></entry><entry><title>Best Python Resources</title><link href="http://caimaoy.github.io/best-python-resources.html" rel="alternate"></link><updated>2015-09-03T23:58:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-09-03:best-python-resources.html</id><summary type="html">&lt;p&gt;翻译了一篇文章，原文链接为 &lt;a href="http://www.fullstackpython.com/best-python-resources.html"&gt;http://www.fullstackpython.com/best-python-resources.html&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Full Stack Python&lt;/h1&gt;
&lt;h2&gt;Best Python Resources&lt;/h2&gt;
&lt;p&gt;Python 社区在分享细节的学习资源和帮助初学者掌握语言方面总是很积极热情的，但是也就是因为太多的资源导致人们很难知道如何找到它们。 
本文整理了最好、最通用的 Python 资源，并且简述了其内容。&lt;/p&gt;
&lt;p&gt;如果您更喜欢通过视频的方式来学习可以点击&lt;a href="http://www.fullstackpython.com/best-python-videos.html"&gt;最好的python视频&lt;/a&gt;。如果有兴趣您也可以阅读一下&lt;a href="http://www.fullstackpython.com/development-environments.html"&gt;代码开发环境&lt;/a&gt;。&lt;/p&gt;
&lt;h3&gt;写给编程新手的&lt;/h3&gt;
&lt;p&gt;如果你是学习第一门编程语言，本小节的书是比较适合你的。如何在学习Python之前你已经学习过其他的编程语言，请跳过此小节直接到下一小节——“有经验的开发者”。  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想要同一时间了解 Python，Django 和 Flask，可以考虑购买Fletcher，Michael和Jeremy三人提供&lt;a href="https://realpython.com/?utm_source=fsp&amp;amp;utm_medium=promo&amp;amp;utm_campaign=bestresources"&gt;Real Python&lt;/a&gt;课程&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=mvK0UzFNw1Q"&gt;短短 5 分钟的视频&lt;/a&gt;告诉你为什么去思考自己想要构建的项目，去编程解决自己想要解决的问题是更好的选择。在这些项目和问题上花心思比一头栽进一个朋友推荐的特定语言要好。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cs.hmc.edu/csforall/"&gt;全民计算机&lt;/a&gt;是一本由哈威穆德学院教授编写的公开图书，教授们使用 Python 教授最基础的计算机科学知识。这本书对初学编程人来说是绝佳的入门读物。&lt;/li&gt;
&lt;li&gt;如果你在点击查看&lt;a href="https://twitter.com/lebdev"&gt;Laurence Bradford&lt;/a&gt;出品的&lt;a href="http://learntocodewith.me/"&gt;跟我学编程&lt;/a&gt;的&lt;a href="http://learntocodewith.me/getting-started/"&gt;开始编程&lt;/a&gt;页面之前重来没有编程经历，她会很好地帮助你。她完成了一个难以置信的工作，将初学者应该完成的步骤进行分解，在他们不知道从何开始的地方给予他们帮助。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://learnpythonthehardway.org/book/"&gt;笨法学 Python&lt;/a&gt;是 Zed Shaw 的 一本免费图书。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.diveinto.org/python3/"&gt;深入 Python 3&lt;/a&gt;是一本提供了知识共享许可协议的开源图书，可获得 HTML 和 PDF 版本。&lt;/li&gt;
&lt;li&gt;虽然不是特定于 Python，Mozilla 提供了针对初级、中级 web 用户和想要建站的人&lt;a href="https://developer.mozilla.org/en-US/Learn"&gt;学习 Web&lt;/a&gt; 的教程。从普通 web 开发者的角度出发值得一看。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.swaroopch.com/notes/python/"&gt;一字节 Python&lt;/a&gt; 是 Python 初学者的教程。&lt;/li&gt;
&lt;li&gt;代码学院有一个 &lt;a href="http://www.codecademy.com/tracks/python"&gt;Python 篇&lt;/a&gt;，适合编程新手。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opentechschool.github.io/python-beginners/en/index.html"&gt;Introduction to Programming with Python&lt;/a&gt; 用 Python介绍基础的语法和结构控制。这本免费图书每个章节都提供了大量的代码示例。&lt;/li&gt;
&lt;li&gt;谷歌提供了大量的材料和主题，如果你想要成为一个&lt;a href="https://www.google.com/about/careers/students/guide-to-technical-development.html"&gt;专业的程序员&lt;/a&gt;，你应该去阅读学习一下。这些资源不仅仅对 Python 初学者有用，对每一个想要在软件开发行业获得更好职业生涯的开发者同样适用。&lt;/li&gt;
&lt;li&gt;O'Reilly 的图书&lt;a href="http://greenteapress.com/thinkpython/html/index.html"&gt;《像计算机科学家一样思考 Python》&lt;/a&gt;在网站中提供免费的 HTML 版本。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://anandology.com/python-practice-book/index.html"&gt;《Python 实践书》&lt;/a&gt;是一本帮你学习 Python 基础语法的练习册。&lt;/li&gt;
&lt;li&gt;寻找学习语言的mini项目，点击查看一下&lt;a href="https://medium.com/learning-journalism-tech/five-mini-programming-projects-for-the-python-beginner-21492f6ce0f3"&gt;这 5 个 Python 项目&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;Reddit 创始人之一在 Udacity 课程上提供了一门如何&lt;a href="https://www.udacity.com/course/web-development--cs253"&gt;用 Python 搭建一个博客&lt;/a&gt;。通过编码介绍了 web 编程的概念。&lt;/li&gt;
&lt;li&gt;我在&lt;a href="http://www.mattmakai.com/learning-python-for-non-developers.html"&gt;学习 Python&lt;/a&gt;这个网站上面写了个博客给没有技术背景的人们学习编程已帮助。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;给有经验但初学 Python 的开发者&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://learnxinyminutes.com/docs/python/"&gt;y 分钟学习 Python&lt;/a&gt; 提供了一个极快速的 Python 教程。这个指南对于先前有软件开发经验并且想快速掌握一门语言结构的人尤其有帮助。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pymbook.readthedocs.org/en/latest/"&gt;你我的 Python&lt;/a&gt; 是一本容易阅读的书，内容包括 Python 的语法和主要的语言结构。本书在结尾还剪短地介绍如何编写第一个 Flask web 应用。&lt;/li&gt;
&lt;li&gt;Kenneth Reitz 的&lt;a href="http://docs.python-guide.org/en/latest/"&gt;Python 漫游指南&lt;/a&gt; 中有大量 Python 编程信息和社区资源 &lt;/li&gt;
&lt;li&gt;&lt;a href="https://districtdatalabs.silvrback.com/how-to-develop-quality-python-code"&gt;如何开发高质量的 Python 代码&lt;/a&gt;是很好的学习开发环境、应用程序依赖关系和项目结构读物。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;高级进阶&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mirnazim.org/writings/python-ecosystem-introduction/"&gt;Python 生态系统&lt;/a&gt;介绍了关于虚拟机，Python 的包管理，pip（管理 Python 包的工具），virutalenv（Python 虚拟环境）等一些在学习完 Python 基础语法之后的学习点。 &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.reddit.com/r/python"&gt;Python Subreddit&lt;/a&gt;上有大量的关于 Python 的链接同时有一个活跃的社区回答 Python 初学者和高级开发者的问题。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jessenoller.com/good-to-great-python-reads/"&gt;Good to Great Python Reads&lt;/a&gt; 收录了网上 Python 关注于 Python 语言本身细节和差异中高级的文章。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://freepythontips.wordpress.com/"&gt;免费的 Python 小建议&lt;/a&gt;这个免费博客上面有一些 Python 的讨论话题，同时也有一些 Python 圈的新闻。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pythonbooks.revolunet.com/"&gt;Python Book&lt;/a&gt;收录了一些 Python， Django和数据分析的免费图书。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://norvig.com/python-iaq.html"&gt;Python 罕见问题&lt;/a&gt;收录了一些关于罕见的 Python 特性的一些提问，并且考虑为什么某些语法是或者不是内建到语言级别的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;视频资源&lt;/h3&gt;
&lt;p&gt;大小聚会的视频在最好的 Python 视频，这个页面上。  &lt;/p&gt;
&lt;h3&gt;有用的 Python 包&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/vinta/awesome-python"&gt;awesome-python&lt;/a&gt; 是一个包含了 Python 框架，Python 库和软件的列表。我真希望我开始学习 Python 的时候有这样惊艳的列表页面。&lt;/li&gt;
&lt;li&gt;和 awesone-python 相似 &lt;a href="http://easy-python.readthedocs.org/en/latest/"&gt;easy-python&lt;/a&gt;，它是一个 Git 仓库的阅读文档格式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;播客&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.talkpythontome.com/"&gt;Talk Python to Me&lt;/a&gt; 这个播客关注写 python 的人和组织。每集会找一个不同类型的嘉宾来介绍他的工作。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://podcastinit.com/"&gt;Podcast.__init__&lt;/a&gt; 是另外一档关于 Python 和其优秀使用者的播客节目。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;新闻资讯&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.pythonweekly.com/"&gt;Python Weekly&lt;/a&gt; 是一个包含了最新 Python 文章、视频、项目和未来大事件的免费周刊。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pycoders.com/"&gt;PyCoder's Weekly&lt;/a&gt; 是和 Python Weekly 相似的优秀的免费邮件新闻周刊。最好的资源两个周刊一般会同时报道，但通常它们会报道网上不同的文章和项目。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://importpython.com/newsletter/"&gt;Import Python&lt;/a&gt; 是一个比 Python Weekly 和 PyCoder's Weekly 更及时的新闻通讯。目前为止，我发现这个新闻通讯的来源和其他两个不同。这个三个资源都值得订阅，这样你就不会错过什么了。&lt;/li&gt;
&lt;/ul&gt;</summary><category term="python"></category><category term="translation"></category></entry><entry><title>windows 迁移 pelican 到 Mac 机器测试</title><link href="http://caimaoy.github.io/test-pelican-on-mac.html" rel="alternate"></link><updated>2015-08-25T18:36:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-08-25:test-pelican-on-mac.html</id><summary type="html">&lt;ul&gt;
&lt;li&gt;就是一个测试&lt;/li&gt;
&lt;li&gt;在Mac机器上面使用pelican，很多的配置都有更改，如果测试通过了，我会把diff贴在下面的&lt;/li&gt;
&lt;li&gt;先看看一下 diff Makefile&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gh"&gt;diff --git a/Makefile b/Makefile&lt;/span&gt;
&lt;span class="gh"&gt;index e69e9c8..c98df1f 100644&lt;/span&gt;
&lt;span class="gd"&gt;--- a/Makefile&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/Makefile&lt;/span&gt;
&lt;span class="gu"&gt;@@ -107,6 +107,12 @@ cf_upload: publish&lt;/span&gt;
        cd $(OUTPUTDIR) &amp;amp;&amp;amp; swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) .

 github: publish
&lt;span class="gi"&gt;+       git add .&lt;/span&gt;
&lt;span class="gi"&gt;+       git ci -a -m &amp;quot;update&amp;quot;&lt;/span&gt;
&lt;span class="gi"&gt;+       git push origin source&lt;/span&gt;
&lt;span class="gi"&gt;+       echo caimaoy.com &amp;gt; $(OUTPUTDIR)/CNAME&lt;/span&gt;
&lt;span class="gi"&gt;+       cp googledabe3ca1b7fa15.html  $(OUTPUTDIR)/googledabe3ca1b7fa15.html&lt;/span&gt;
        ghp-import -m &amp;quot;Generate Pelican site&amp;quot; -b $(GITHUB_PAGES_BRANCH) $(OUTPUTDIR)
        git push origin $(GITHUB_PAGES_BRANCH)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;使用上面的命令进行提交&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;因为是从 windows 迁移到mac机器上面，所以配置文件的分隔符要修改一下&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gh"&gt;diff --git a/publishconf.py b/publishconf.py&lt;/span&gt;
&lt;span class="gh"&gt;index 30d0156..bfb60d8 100644&lt;/span&gt;
&lt;span class="gd"&gt;--- a/publishconf.py&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/publishconf.py&lt;/span&gt;
&lt;span class="gu"&gt;@@ -88,7 +88,7 @@ USE_FOLDER_AS_CATEGORY = True&lt;/span&gt;

 # plugin config
 # PLUGIN_PATHS = [&amp;#39;./plugins&amp;#39;]
&lt;span class="gd"&gt;-PLUGIN_PATHS = [r&amp;#39;.\pelican-plugins&amp;#39;]&lt;/span&gt;
&lt;span class="gi"&gt;+PLUGIN_PATHS = [r&amp;#39;./pelican-plugins&amp;#39;]&lt;/span&gt;
 PLUGINS = [
     #&amp;#39;pandoc_reader&amp;#39;,
     #&amp;#39;gzip_cache&amp;#39;,
&lt;span class="gu"&gt;@@ -121,4 +121,4 @@ SITEMAP = {&lt;/span&gt;

 # THEME = r&amp;#39;.\pelican-themes\bootstrap2-dark&amp;#39;
 # THEME = r&amp;#39;.\pelican-themes\SoMA&amp;#39;
&lt;span class="gd"&gt;-THEME = r&amp;#39;.\pelican-themes\pelican-bootstrap3&amp;#39;&lt;/span&gt;
&lt;span class="gi"&gt;+THEME = r&amp;#39;./pelican-themes/pelican-bootstrap3&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;主题文件和插件文件因为是在另外的两个git仓库里面，不需要修改&lt;/li&gt;
&lt;li&gt;一切看起来还很美好？！&lt;/li&gt;
&lt;li&gt;NO！ Tags 不见了！&lt;/li&gt;
&lt;li&gt;生产过程中没有报错，目前还在排查中！&lt;/li&gt;
&lt;li&gt;囧！但是我已经上线了，又不想回滚 555&lt;/li&gt;
&lt;/ul&gt;</summary><category term="test"></category><category term="mac"></category><category term="pelican"></category><category term="python"></category></entry><entry><title>Introduction of SOAP</title><link href="http://caimaoy.github.io/introduction-of-soap.html" rel="alternate"></link><updated>2015-08-13T10:14:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-08-13:introduction-of-soap.html</id><summary type="html">&lt;h3&gt;SOAP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;这里说的SOAP不是肥皂，和捡肥皂也没有关系&lt;/li&gt;
&lt;li&gt;先来看一下官方介绍,以下内容来自&lt;a href="https://zh.wikipedia.org/wiki/SOAP"&gt;wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;SOAP（原为Simple Object Access Protocol的首字母缩写，即简单对象访问协议）是交换数据的一种协议规范，使用在计算机网络Web服务（web service）中，交换带结构信息。SOAP为了简化网页服务器（Web Server）从XML数据库中提取数据时，节省去格式化页面时间，以及不同应用程序之间按照HTTP通信协议，遵从XML格式执行资料互换，使其抽象于语言实现、平台和硬件。此标准由IBM、Microsoft、UserLand和DevelopMentor在1998年共同提出，并得到IBM，莲花（Lotus），康柏（Compaq）等公司的支持，于2000年提交给万维网联盟（World Wide Web Consortium；W3C），目前SOAP 1.1版是业界共同的标准，属于第二代的XML协定（第一代具主要代表性的技术为XML-RPC以及WDDX）。

用一个简单的例子来说明SOAP使用过程，一个SOAP消息可以发送到一个具有Web Service功能的Web站点，例如，一个含有房价信息的数据库，消息的参数中标明这是一个查询消息，此站点将返回一个XML格式的信息，其中包含了查询结果（价格，位置，特点，或者其他信息）。由于数据是用一种标准化的可分析的结构来传递的，所以可以直接被第三方站点所利用。
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;上面的话翻译一下，就是SOAP 是基于 XML 的简易协议，可使应用程序在 HTTP 之上进行信息交换。&lt;/li&gt;
&lt;li&gt;或者更简单地说：SOAP 是用于访问网络服务的协议。&lt;/li&gt;
&lt;li&gt;还是不够清晰？ 看看实例吧&lt;/li&gt;
&lt;li&gt;在下面的例子中，一个 GetStockPrice 请求被发送到了服务器。此请求有一个 StockName 参数，而在响应中则会返回一个 Price 参数。此功能的命名空间被定义在此地址中： "http://www.example.org/stock"&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SOAP 请求:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nf"&gt;POST&lt;/span&gt; &lt;span class="nn"&gt;/InStock&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;www.example.org&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/soap+xml; charset=utf-8&lt;/span&gt;
&lt;span class="na"&gt;Content-Length&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;nnn&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;soap:Envelope&lt;/span&gt;
&lt;span class="na"&gt;xmlns:soap=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/2001/12/soap-envelope&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;soap:encodingStyle=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/2001/12/soap-encoding&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;soap:Body&lt;/span&gt; &lt;span class="na"&gt;xmlns:m=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.example.org/stock&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;m:GetStockPrice&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;m:StockName&amp;gt;&lt;/span&gt;IBM&lt;span class="nt"&gt;&amp;lt;/m:StockName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/m:GetStockPrice&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/soap:Body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/soap:Envelope&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;SOAP 响应：&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn

&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;soap:Envelope&lt;/span&gt;
&lt;span class="na"&gt;xmlns:soap=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/2001/12/soap-envelope&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;soap:encodingStyle=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/2001/12/soap-encoding&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;soap:Body&lt;/span&gt; &lt;span class="na"&gt;xmlns:m=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.example.org/stock&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;m:GetStockPriceResponse&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;m:Price&amp;gt;&lt;/span&gt;34.5&lt;span class="nt"&gt;&amp;lt;/m:Price&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/m:GetStockPriceResponse&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/soap:Body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/soap:Envelope&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;各种问题&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;现在问题来了，SOAP只是一个传输协议&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;h3&gt;Web Service&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;要解答问题就要先了解&lt;a href="https://zh.wikipedia.org/wiki/Web%E6%9C%8D%E5%8A%A1"&gt;Web服务&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;Web服务是一种服务导向架构的技术，通过标准的Web协议提供服务，目的是保证不同平台的应用服务可以互操作。

根据W3C的定义，Web服务（Web service）应当是一个软件系统，用以支持网络间不同机器的互动操作。网络服务通常是许多应用程序接口（API）所组成的，它们透过网络，例如国际互联网（Internet）的远程服务器端，执行客户所提交服务的请求。

尽管W3C的定义涵盖诸多相异且无法介分的系统，不过通常我们指有关于主从式架构（Client-server）之间根据SOAP协议进行传递XML格式消息。无论定义还是实现，WEB服务过程中会由服务器提供一个机器可读的描述（通常基于WSDL）以辨识服务器所提供的WEB服务。另外，虽然WSDL不是SOAP服务端点的必要条件，但目前基于Java的主流WEB服务开发框架往往需要WSDL实现客户端的源代码生成。一些工业标准化组织，比如WS-I，就在WEB服务定义中强制包含SOAP和WSDL。
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;提问：我们为什么要用web服务？&lt;/li&gt;
&lt;li&gt;回答：Webservice的一个最基本的目的就是提供在各个不同平台的不同应用系统的协同工作能力&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;我肤浅的认为WebService有以下几个好处：&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;/li&gt;
&lt;li&gt;
&lt;p&gt;提问：我们为什么不用基于URI的方式来请求Web服务？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;回答：基于URI的方式的确是一种方法，是Web Service 的另一种解决方案：REST，这里不详细说明了&lt;/li&gt;
&lt;li&gt;基于SOAP传输，是考虑到数据类型多样化和服务器解析压力小两个原因&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;WSDL&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;好像还是有问题&lt;/li&gt;
&lt;li&gt;提问：我如何去哪请求服务？请求参数是什么啊？&lt;/li&gt;
&lt;li&gt;回答：WSDL 是 Web Services Description Language 的所写，也就是 Web 服务的描述&lt;/li&gt;
&lt;li&gt;简单的说它描述了你向哪个地址和端口发送消息、请求消息格式、接收消息格式等信息&lt;/li&gt;
&lt;li&gt;客户端有了这些信息就可以像调用一个本地函数一样调用一个Web Service&lt;/li&gt;
&lt;li&gt;下面为python调用web Service的一种方法：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;suds.client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:7789/SOAP/?wsdl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary><category term="soap webservice"></category></entry><entry><title>如何用axis的wsdd方法部署WebService</title><link href="http://caimaoy.github.io/how-to-deploy-webservice-by-axis-wsdd.html" rel="alternate"></link><updated>2015-08-05T15:36:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-08-05:how-to-deploy-webservice-by-axis-wsdd.html</id><summary type="html">&lt;h2&gt;编写 deploy.wsdd 文件&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;放置于 %Tomcat_Home%\webapps\axis\WEB-INF 中&lt;/li&gt;
&lt;li&gt;内容如下&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;deployment&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://xml.apache.org/axis/wsdd/&amp;quot;&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:java=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://xml.apache.org/axis/wsdd/providers/java&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;WSDD&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;java:RPC&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;className&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;com.caimaoy&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- * 代表所有的方法都暴露 --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;allowedMethods&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;*&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;scope&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;request&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/deployment&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;service标签代表一个WebService服务，HelloWorldWSDD就是当前WebService的名称&lt;/li&gt;
&lt;li&gt;provider是java的WebService类型，分别有： RPC、Document、Wrapped、Message、EJB、RMI&lt;/li&gt;
&lt;li&gt;有兴趣的可以看看org.apache.axis.providers.java包下面的WebService的实现类或是文档&lt;/li&gt;
&lt;li&gt;parameter的参数className代表当前WebService的class类路径&lt;/li&gt;
&lt;li&gt;allowedMethods代表暴露的方法，那些方法在客户端可以调用；&lt;/li&gt;
&lt;li&gt;&lt;parameter name="scope" value="request" /&gt;&lt;/li&gt;
&lt;li&gt;这个是当前WebService的作用域，它有3个值，分别是：request、session、application&lt;/li&gt;
&lt;li&gt;request代表为每个WebService SOAP的请求都产生一个服务对象，和Spring的scope很像，在服务请求频繁的话会消耗很多资源&lt;/li&gt;
&lt;li&gt;session 是给每个调用当前WebService的客户端创建一个服务对象&lt;/li&gt;
&lt;li&gt;application 是个当前所有的请求创建一个服务对象&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;发布 WebService&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;写完配置后，就需要用axis提供的AdminClient工具类帮我们发布WebService，直到生成server-config.wsdd&lt;/li&gt;
&lt;li&gt;步骤如下:&lt;/li&gt;
&lt;li&gt;启动Tomcat&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;运行cmd命令，然后进入当前工程发布的目录，即%tomcat_home%/webapps/project/WEB-INF&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输入命令&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient deploy.wsdd
java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient -p 8082 -s /axis/servlet/AxisServlet deploy.wsdd
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;-p 表示端口Tomcat端口号，AdminClient 默认为__8080__&lt;/li&gt;
&lt;li&gt;这里的deploy.wsdd是我们刚才定制的wsdd文件，java当然是jvm的命令&lt;/li&gt;
&lt;li&gt;-Djava.ext.dirs=lib设置当前命令的依赖包&lt;/li&gt;
&lt;li&gt;AdminClient是axis提供的工具类，这个类本来是可以在官方的工程中admin可以直接运行的（这里不可以，下载下来的少了AdminServlet，有兴趣的可以研究下，就是前面说的官方的示例）；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果运行命令后，看到：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;Processing file deploy.wsdd
&lt;span class="nt"&gt;&amp;lt;Admin&amp;gt;&lt;/span&gt;Done processing&lt;span class="nt"&gt;&amp;lt;/Admin&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;就代表快成功了，why？快！看看deploy.wsdd同级目录有没有生成server-config.wsdd如果有这个文件就成功了，没有就失败了&lt;/li&gt;
&lt;li&gt;如果失败了还有解决办法，首先你得启动tomcat，将我们的工程发布出去。然后在重复上面的命令，不行就换命令行代码如下：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient -lhttp://localhost:8080/AxisWebService/services/AdminService deploy.wsdd
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;-lhttp://localhost:8080/AxisWebService/services/AdminService是因为你的端口可能被axis占用了，我们将指定AdminService来完成转换，运行上面命令就没有问题了。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;WebService 客户端&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;我这里只说一种客户端的实现方法，在网上看了好像有超过6种以上的方法&lt;/li&gt;
&lt;li&gt;大概的代码如下：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.axis.client.Call&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.axis.client.Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.xml.namespace.QName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;http://caimaoy.com/axis/services/WSDD?wsdl=1&amp;amp;test=test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Service&lt;/span&gt;  &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Call&lt;/span&gt;  &lt;span class="n"&gt;call&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createCall&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTargetEndpointAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setOperationName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;QName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://soapinterop.org/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;querySingle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Hello!&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;got:&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;提问：如果我出现了 java.lang.reflect.InvocationTargetException 这样的异常如何处理？&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;回答：这是映射出错，我遇到的情况是在 %Tomcat_Home%\webapps\axis\WEB-INF 中添加缺失是jar包&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;提问：作为一个WebService能够获取到客户端的IP、请求的requestString吗？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;回答：可以大概的获取方式如下,获取到了 HttpServletRequest requsest,也就有了想要的东西了&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.axis.MessageContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.axis.transport.http.HTTPConstants&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorld&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;getClientInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;asYouLike&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
        &lt;span class="n"&gt;MessageContext&lt;/span&gt; &lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MessageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getCurrentMessageContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MessageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getCurrentContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;无法获取到MessageContext&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpServletRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HTTPConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MC_HTTP_SERVLETREQUEST&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;remote  ip:  &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRemoteAddr&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;request URI:  &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRequestURI&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;quesryString :  &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getQueryString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printStackTrace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</summary><category term="java"></category><category term="webservice"></category><category term="axis"></category><category term="wsdd"></category></entry><entry><title>python re.sub</title><link href="http://caimaoy.github.io/python-re-sub.html" rel="alternate"></link><updated>2015-07-13T11:17:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-07-13:python-re-sub.html</id><summary type="html">&lt;ul&gt;
&lt;li&gt;经常遇到使用re.sub的情况，但经常忘记，所以记录一下&lt;/li&gt;
&lt;li&gt;首先还是看看大神的简介：&lt;a href="http://www.crifan.com/python_re_sub_detailed_introduction/"&gt;crifan【整理】详解Python中re.sub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sub(pattern, repl, string, count=0, flags=0)
    Return the string obtained by replacing the leftmost
    non-overlapping occurrences of the pattern in string by the
    replacement repl.  repl can be either a string or a callable;
    if a string, backslash escapes in it are processed.  If it is
    a callable, it&amp;#39;s passed the match object and must return
    a replacement string to be used.
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/2/library/re.html#re.sub"&gt;re.sub官方文档&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用法和功能我就不详述了，下面看看一些奇葩需求&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;首先是换位的需求&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;def change_place(s):
    &amp;#39;&amp;#39;&amp;#39;
    &amp;gt;&amp;gt;&amp;gt; change_place(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
    &amp;#39;jessie&amp;amp;caimaoy&amp;#39;
    &amp;#39;&amp;#39;&amp;#39;
    return re.sub(r&amp;#39;(caimaoy)(&amp;amp;)(jessie)&amp;#39;, r&amp;#39;\3\2\1&amp;#39;, s)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;然后是换位换字符的需求&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;def change_place_and_joiner(s):
    &amp;#39;&amp;#39;&amp;#39;
    &amp;gt;&amp;gt;&amp;gt; change_place_and_joiner(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
    &amp;#39;jessie with caimaoy&amp;#39;
    &amp;#39;&amp;#39;&amp;#39;
    return re.sub(r&amp;#39;(caimaoy)(&amp;amp;)(jessie)&amp;#39;, r&amp;#39;\3 with \1&amp;#39;, s)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;看起来不错，但是如果我要换的字符是数值，会发生什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;def change_place_and_joiner_with_number(s):
    &amp;#39;&amp;#39;&amp;#39;
    &amp;gt;&amp;gt;&amp;gt; change_place_and_joiner_with_number(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
    &amp;#39;jessie0caimaoy&amp;#39;
    &amp;#39;&amp;#39;&amp;#39;
    return re.sub(r&amp;#39;(caimaoy)(&amp;amp;)(jessie)&amp;#39;, r&amp;#39;\30\1&amp;#39;, s)
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;File &amp;quot;test_doc_test.py&amp;quot;, line 37, in __main__.change_place_and_joiner_with_numbe
r
Failed example:
    change_place_and_joiner_with_number(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
Exception raised:
    Traceback (most recent call last):
      File &amp;quot;D:\Python27\lib\doctest.py&amp;quot;, line 1289, in __run
        compileflags, 1) in test.globs
      File &amp;quot;&amp;lt;doctest __main__.change_place_and_joiner_with_number[0]&amp;gt;&amp;quot;, line 1,
in &amp;lt;module&amp;gt;
        change_place_and_joiner_with_number(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
      File &amp;quot;test_doc_test.py&amp;quot;, line 40, in change_place_and_joiner_with_number
        return re.sub(r&amp;#39;(caimaoy)(&amp;amp;)(jessie)&amp;#39;, r&amp;#39;\30\1&amp;#39;, s)
      File &amp;quot;D:\Python27\lib\re.py&amp;quot;, line 151, in sub
        return _compile(pattern, flags).sub(repl, string, count)
      File &amp;quot;D:\Python27\lib\re.py&amp;quot;, line 275, in filter
        return sre_parse.expand_template(template, match)
      File &amp;quot;D:\Python27\lib\sre_parse.py&amp;quot;, line 789, in expand_template
        raise error, &amp;quot;invalid group reference&amp;quot;
    error: invalid group reference
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;报错了！大概的描述就是我们根本就没有30这个组&lt;/li&gt;
&lt;li&gt;如何解决？看看文档，下面是解决方案，&lt;strong&gt;用\g&lt;n&gt;来替代\n&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;def change_place_and_joiner_with_number(s):
    &amp;#39;&amp;#39;&amp;#39;
    &amp;gt;&amp;gt;&amp;gt; change_place_and_joiner_with_number(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
    &amp;#39;jessie0caimaoy&amp;#39;
    &amp;#39;&amp;#39;&amp;#39;
    return re.sub(r&amp;#39;(caimaoy)(&amp;amp;)(jessie)&amp;#39;, r&amp;#39;\g&amp;lt;3&amp;gt;0\g&amp;lt;1&amp;gt;&amp;#39;, s)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;好像没有进一步的需求了，其实上面的需求re.sub的第二个参数传入一个函数是可以解决的&lt;/li&gt;
&lt;li&gt;不过就是懒（优秀品质）&lt;/li&gt;
&lt;li&gt;最后给一个传入函数的例子&lt;/li&gt;
&lt;li&gt;要replace为大写&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;def change_place_and_upper(s):
    &amp;#39;&amp;#39;&amp;#39;
    &amp;gt;&amp;gt;&amp;gt; change_place_and_upper(&amp;#39;caimaoy&amp;amp;jessie&amp;#39;)
    &amp;#39;JESSIE&amp;amp;CAIMAOY&amp;#39;
    &amp;#39;&amp;#39;&amp;#39;
    def _upper(matched):
        return matched.group(3).upper() + matched.group(2) + matched.group(1).upper()
    return re.sub(r&amp;#39;(caimaoy)(&amp;amp;)(jessie)&amp;#39;, _upper, s)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;看看以后还有什么需求，估计传入函数基本都能解决&lt;/li&gt;
&lt;/ul&gt;</summary><category term="python"></category></entry><entry><title>HHKB初体验</title><link href="http://caimaoy.github.io/diary-HHKB.html" rel="alternate"></link><updated>2015-06-16T20:01:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-06-16:diary-HHKB.html</id><summary type="html">&lt;h3&gt;首先庆祝一下COC冠军杯&lt;/h3&gt;
&lt;p&gt;&lt;img alt="COC冠军杯" src="http://7xif3g.com1.z0.glb.clouddn.com/COC冠军杯.PNG" /&gt;&lt;/p&gt;
&lt;h3&gt;今天的主角: HHKB&lt;/h3&gt;
&lt;p&gt;&lt;img alt="HHKB" src="http://7xif3g.com1.z0.glb.clouddn.com/HHKB.JPG" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同事漂洋过海从岛国带回一个无刻版HHKB Pro2&lt;/li&gt;
&lt;li&gt;因为是无刻版，到现在都非常痛苦&lt;/li&gt;
&lt;li&gt;不记得键位，所以下面先来一个HHKB Professional 2 Layout&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="HHKB Professional 2 Layout" src="http://7xif3g.com1.z0.glb.clouddn.com/HHKB_Pro2_Layout.jpg" /&gt;&lt;/p&gt;
&lt;h4&gt;键盘设置&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;什么？键盘还要设置？又不是鼠标还要设置PPI？&lt;/li&gt;
&lt;li&gt;是的你没有听错，这键盘就是要设置，主要是满足不同系统需要&lt;/li&gt;
&lt;li&gt;HHKB Pro 2 是有一排跳线6个开关，理论上是可以有2^6==64种不同的组合&lt;/li&gt;
&lt;li&gt;先来看看跳线的模式说明&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="跳线模式" src="http://7xif3g.com1.z0.glb.clouddn.com/HHKB_跳线说明.JPG" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;再来看看跳线前两位模式的说明
&lt;img alt="模式说明" src="http://7xif3g.com1.z0.glb.clouddn.com/HHKB_模式说明.JPG" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果看懂了这个，你也就配置好了自己的键盘&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;本人配置&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;本人工作在windos环境！（对！你没有看错，就是万恶的windows！！！）&lt;/li&gt;
&lt;li&gt;跳线打开1、3、5&lt;/li&gt;
&lt;li&gt;Delete键改为BackSpace键&lt;/li&gt;
&lt;li&gt;最下面一排按键为：win、alt、空格、alt、win&lt;/li&gt;
&lt;li&gt;这样基本满足在windows下面的操作&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;FAQ&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;- 如何退格？
- 使用Fn + Delete 或者跳线3打开使用Delete
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;- 如何关闭窗口？
- 使用Alt + Fn + F4 或者有些窗口可以使用Ctrl + w
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;- 如何在Vim中按Esc？
- 这个要算是我很痛苦的一个问题了
- 我本来通过注册表吧Caps和Esc的位置调换了
- 现在Caps的位置变成了Ctrl

- 方案一：
- 直接按 Esc

- 方案二：
- &amp;lt;C-[&amp;gt;在vim中也是Esc
- 但是我还没有习惯，经常按错成&amp;lt;C-p&amp;gt;,同时经常把Shift按成Ctrl

- 方案三：
- 黑魔法 jk 或者 jj 或者什么 map到Esc
- 我个人试验过，个人不习惯
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;- 上下左右如何按？
- Fn + [/;&amp;#39;
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;- 翻页、End如何按？
- Fn + keyboard layout 自己看了
- 反正我是打印了一个layout在桌面上，囧
&lt;/pre&gt;&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;这是我用HHKB在Vim下面写的第一篇文章，误操作无数
 希望慢慢能够适应
 HHKB真的手感超一流，相比原厂CHERRY，我更喜欢HHKB的手感
 希望有体验的大神们，告诉一下小白我更多tips，THX&lt;/p&gt;
&lt;/blockquote&gt;</summary><category term="diary"></category><category term="HHKB"></category></entry><entry><title>python const</title><link href="http://caimaoy.github.io/python-const.html" rel="alternate"></link><updated>2015-06-10T16:55:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-06-10:python-const.html</id><summary type="html">&lt;ul&gt;
&lt;li&gt;python 没有const 这样的语法，但是在项目中可能会有这样的需求？&lt;/li&gt;
&lt;li&gt;自己动手丰衣足食！！！&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;const.py&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;首先创建一个const.py文件，代码如下&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;Last modified time: 2015-06-09 09:49:29&lt;/span&gt;
&lt;span class="sd"&gt;Edit time: 2015-06-09 09:55:07&lt;/span&gt;
&lt;span class="sd"&gt;File name: const.py&lt;/span&gt;
&lt;span class="sd"&gt;Edit by caimaoy&lt;/span&gt;
&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;__author__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_const&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConstError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConstCaseError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__setattr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConstError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Can&amp;#39;t change const. &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isupper&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConstCaseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; \
                    &lt;span class="s"&gt;&amp;#39;const name &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot; is not all uppercase&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;


&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_const&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;使用代理模式，代理类的__setattr__方法&lt;/li&gt;
&lt;li&gt;判断是否键值，抛出自定义的Error类&lt;/li&gt;
&lt;li&gt;判断键值格式是否符合要求，抛出自定义的Error类&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_const&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c"&gt;# &amp;lt;&amp;lt;&amp;lt;使加载此模块指向_const()类&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;test_const.py&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;Last modified time: 2015-06-10 17:14:54&lt;/span&gt;
&lt;span class="sd"&gt;Edit time: 2015-06-10 17:15:21&lt;/span&gt;
&lt;span class="sd"&gt;File name: test_cosnt.py&lt;/span&gt;
&lt;span class="sd"&gt;Edit by caimaoy&lt;/span&gt;
&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;__author__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;const&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_cosnt_error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;jessie&amp;#39;&lt;/span&gt;  &lt;span class="c"&gt;# &amp;lt;&amp;lt;&amp;lt; ConstError(&amp;quot;Can&amp;#39;t change const. NAME&amp;quot;,)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_cosnt_case_error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt; &lt;span class="c"&gt;# &amp;lt;&amp;lt;&amp;lt; ConstCaseError(&amp;#39;const name &amp;quot;name&amp;quot; is not all uppercase&amp;#39;,)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;catch_error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;test_cosnt_error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;test_cosnt_case_error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;catch_error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;对于const.py的测试&lt;/li&gt;
&lt;li&gt;运行结果如下,符合预期&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;ConstError(&amp;quot;Can&amp;#39;t change const. NAME&amp;quot;,)
ConstCaseError(&amp;#39;const name &amp;quot;name&amp;quot; is not all uppercase&amp;#39;,)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;如果有需求可以代理__del__方法，保证常量不会被del&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;constant.py&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;当然我们通常把所有的常量写入一个文件，方便管理&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;Last modified time: 2015-06-10 17:38:12&lt;/span&gt;
&lt;span class="sd"&gt;Edit time: 2015-06-10 17:38:17&lt;/span&gt;
&lt;span class="sd"&gt;File name: constant.py&lt;/span&gt;
&lt;span class="sd"&gt;Edit by caimaoy&lt;/span&gt;
&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;__author__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;const&lt;/span&gt;

&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Monster Hunter&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;使用的方法如下&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="sd"&gt;Last modified time: 2015-06-10 17:40:28&lt;/span&gt;
&lt;span class="sd"&gt;Edit time: 2015-06-10 17:40:35&lt;/span&gt;
&lt;span class="sd"&gt;File name: use_const.py&lt;/span&gt;
&lt;span class="sd"&gt;Edit by caimaoy&lt;/span&gt;
&lt;span class="sd"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;__author__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;constant&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;const&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;use_const&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;const.NAME is &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;const.GAME is &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GAME&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;use_const&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;结果当然是预期的情况&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;const.NAME is caimaoy
const.GAME is Monster Hunter
&lt;/pre&gt;&lt;/div&gt;</summary><category term="python"></category></entry><entry><title>python split</title><link href="http://caimaoy.github.io/python-split.html" rel="alternate"></link><updated>2015-05-07T10:14:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-05-07:python-split.html</id><summary type="html">&lt;h3&gt;str.split&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;Help on method_descriptor:

split(...)
    S.split([sep [,maxsplit]]) -&amp;gt; list of strings

    Return a list of the words in the string S, using sep as the
    delimiter string.  If maxsplit is given, at most maxsplit
    splits are done. If sep is not specified or is None, any
    whitespace string is a separator and empty strings are removed
    from the result.
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;基本用法&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [5]: &amp;#39;caimaoy jessie HHKB Tesla&amp;#39;.split(&amp;#39; &amp;#39;)
Out[5]: [&amp;#39;caimaoy&amp;#39;, &amp;#39;jessie&amp;#39;, &amp;#39;HHKB&amp;#39;, &amp;#39;Tesla&amp;#39;]
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;re.split&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;Help&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;split&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxsplit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;Split&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;occurrences&lt;/span&gt; &lt;span class="nx"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;returning&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="nx"&gt;containing&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;resulting&lt;/span&gt; &lt;span class="nx"&gt;substrings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;基本用法&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [14]: re.split(r&amp;#39;\d&amp;#39;, &amp;#39;caimaoy1jessie2HHKB3Tesla&amp;#39;)
Out[14]: [&amp;#39;caimaoy&amp;#39;, &amp;#39;jessie&amp;#39;, &amp;#39;HHKB&amp;#39;, &amp;#39;Tesla&amp;#39;]
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;迷惑用法&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [15]: re.split(&amp;#39;o(o)&amp;#39;, &amp;#39;foobar&amp;#39;)
Out[15]: [&amp;#39;f&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;bar&amp;#39;]
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;这是发生了什么啊？&lt;/li&gt;
&lt;li&gt;书里面的解释&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;如果模式包括小括号，那么括起来的字符组合会散布在分割后的字字符串之间&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;不过上面的例子还是很让人迷惑，还是自己写几个&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [19]: re.split(&amp;#39;(and)&amp;#39;, &amp;#39;caimaoyandjessie&amp;#39;)
Out[19]: [&amp;#39;caimaoy&amp;#39;, &amp;#39;and&amp;#39;, &amp;#39;jessie&amp;#39;]

In [20]: re.split(&amp;#39;o(and)o&amp;#39;, &amp;#39;caimaoyoandojessie&amp;#39;)
Out[20]: [&amp;#39;caimaoy&amp;#39;, &amp;#39;and&amp;#39;, &amp;#39;jessie&amp;#39;]

In [21]: re.split(r&amp;#39;(\d)&amp;#39;, &amp;#39;caimaoy3jessie&amp;#39;)
Out[21]: [&amp;#39;caimaoy&amp;#39;, &amp;#39;3&amp;#39;, &amp;#39;jessie&amp;#39;]
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;相信这几个例子写了之后就没有那么迷惑了&lt;/li&gt;
&lt;/ul&gt;</summary><category term="python"></category></entry><entry><title>VIM 去掉重复行</title><link href="http://caimaoy.github.io/vim-removing-duplicate-lines.html" rel="alternate"></link><updated>2015-05-06T10:57:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-05-06:vim-removing-duplicate-lines.html</id><summary type="html">&lt;h3&gt;不难理解的方法&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;先想想思路:&lt;ul&gt;
&lt;li&gt;先排序&lt;/li&gt;
&lt;li&gt;然后去掉重复的行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;看看具体命令&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;:sort u
g/^\(.*\)\n\1$/d
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;下面讲解一下：&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;:sort u             &amp;lt;-- 排序
g/^\(.*\)\n\1$/d    &amp;lt;-- kjkj
g/            /d    &amp;lt;-- g命令delete 满足要求的行
  ^\(.*\)\n         &amp;lt;-- 一行的开始到换行
           \1$      &amp;lt;-- \1 是前面(.*\)的内容，也就是说和前面的行内容相等
             $      &amp;lt;-- 结束符，两行相等是匹配条件
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;一些高级vim语法的操作&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://vim.wikia.com/wiki/Uniq_-_Removing_duplicate_lines"&gt;参考博文&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先看一下命令&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;g/\%(^\1\n\)\@&amp;lt;=\(.*\)$/d
g/\v%(^\1\n)@&amp;lt;=(.*)$/d
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;看一下原本博客中的解释&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;g/\%(^\1\n\)\@&amp;lt;=\(.*\)$/d
g/                     /d  &amp;lt;-- Delete the lines matching the regexp
            \@&amp;lt;=           &amp;lt;-- If the bit following matches, make sure the bit preceding this symbol directly precedes the match
                \(.*\)$    &amp;lt;-- Match the line into subst register 1
  \%(     \)               &amp;lt;-- Group without placing in a subst register.
     ^\1\n                 &amp;lt;-- Match subst register 1 followed the new line between the 2 lines
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;这里面有一个reg的知识点：&lt;strong&gt;环视&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;\@&amp;lt;= 这是一个逆向环视&lt;/li&gt;
&lt;li&gt;所以建议大家还是用第一种方法就好了&lt;/li&gt;
&lt;/ul&gt;</summary><category term="vim"></category></entry><entry><title>Jessie English</title><link href="http://caimaoy.github.io/Jessie-English.html" rel="alternate"></link><updated>2015-11-05T22:53:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-22:Jessie-English.html</id><summary type="html">&lt;h3&gt;prefix &amp;amp; root&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://caimaoy.gitbooks.io/jessie-prefix-root/content/"&gt;content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gitbook.com/book/caimaoy/jessie-prefix-root/details"&gt;details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gitbook.com/download/pdf/book/caimaoy/jessie-prefix-root"&gt;pdf_download_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;writing words&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://caimaoy.github.io/Jessie-English"&gt;for_more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gitbook.com/book/caimaoy/jessie-writing-words/details"&gt;details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gitbook.com/download/pdf/book/caimaoy/jessie-writing-words"&gt;pdf_download_link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary><category term="English"></category></entry><entry><title>pyinstaller生成exe中文路径无法运行解决方案</title><link href="http://caimaoy.github.io/pyinstaller-chinese-dir.html" rel="alternate"></link><updated>2015-04-15T20:14:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-15:pyinstaller-chinese-dir.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;pyinstaller生成的exe中文路径不能运行，错误信息如下:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;D:\测试&amp;gt;&amp;quot;D:\测试\caimaoy_tool.exe&amp;quot;
Traceback (most recent call last):
  File &amp;quot;&amp;lt;string&amp;gt;&amp;quot;, line 21, in &amp;lt;module&amp;gt;
  File &amp;quot;D:\Python27\Lib\site-packages\PyInstaller\loader\pyi_importers.py&amp;quot;, line
 507, in install
  File &amp;quot;D:\Python27\Lib\site-packages\PyInstaller\loader\pyi_importers.py&amp;quot;, line
 156, in __init__
ImportError: Can&amp;#39;t load frozen modules.
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;直接上&lt;a href="http://hi.baidu.com/domhow/item/341817d1afd5a558ddf9bee9"&gt;解决方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;在此&lt;a href="https://github.com/dkw72n/pyinstaller/tree/develop"&gt;安装pyinstaller&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;但是介于他是百度空间的东西我还是备份一下的好，以下内容摘抄自解决方案&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;原文&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;想修改windows的默认字符集为 utf8 的  &lt;/p&gt;
&lt;p&gt;请参考这篇 &lt;a href="http://superuser.com/questions/239810/setting-utf8-as-default-character-encoding-in-windows-7"&gt;http://superuser.com/questions/239810/setting-utf8-as-default-character-encoding-in-windows-7&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;本质问题是他把我们的目录当成是utf8编码的.  &lt;/p&gt;
&lt;p&gt;然后, 只能看代码了. 发现 bootloader 里有个 stb_to_utf8 和 stb_from_utf8  &lt;/p&gt;
&lt;p&gt;而且是 放在 #ifdef _WIN32 里的! =.= 里面正经地实现了 UTF16 &amp;lt;-&amp;gt; UTF8 .
于是. 把这两个函数用 MultiByteToWideChar WideCharToMultiByte 改了.重新编译.好了.  &lt;/p&gt;
&lt;p&gt;然后我 fork 过来改了. &lt;a href="https://github.com/dkw72n/pyinstaller/tree/develop"&gt;https://github.com/dkw72n/pyinstaller/tree/develop&lt;/a&gt; 有需要的可以来取.  &lt;/p&gt;
&lt;p&gt;(顺便整理下走过的弯路, 开始时已经知道是是模块加载的时候编码不对了, 只是一直纠结在''我怎么在模块加载的时候强行把他    的错误编码掰过来''. 无果. 可能的原因是那个阶段编码相关模块没被加载.)  &lt;/p&gt;
&lt;p&gt;另外: 感谢 ikadog 同学两度把这个链接贴到了官方的ticket[&lt;a href="http://trac.pyinstaller.org/ticket/901"&gt;1&lt;/a&gt;,&lt;a href="http://trac.pyinstaller.org/ticket/824"&gt;2&lt;/a&gt;]. 不过貌似他们没打算处理.  &lt;/p&gt;
&lt;p&gt;# update(2014_09_01): 之前没有编译64位的bootloader，用64位的同学直接取下来会发现还是不能用，今天补上了，之前不行的可以再试试。  &lt;/p&gt;
&lt;/blockquote&gt;</summary><category term="pyinstaller"></category><category term="python"></category></entry><entry><title>PyQt 创建新窗口</title><link href="http://caimaoy.github.io/pyqt_create_a_new_window.html" rel="alternate"></link><updated>2015-04-15T19:36:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-15:pyqt_create_a_new_window.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;PyQt 如何新建一个窗口&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PyQt4.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PyQt4.QtGui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;mainWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QPushButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;u&amp;#39;弹出新窗口&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slavewindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slaveWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SIGNAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;clicked()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slavewindow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;slaveWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slaveWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mainwindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mainWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mainwindow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec_&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;直接上代码&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;备注&lt;/h3&gt;
&lt;p&gt;说说要注意的吧:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;self.slavewindow = slaveWindow()
self.connect(button, SIGNAL(&amp;#39;clicked()&amp;#39;), self.slavewindow.show)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;这两个是关键&lt;/li&gt;
&lt;li&gt;之前自己一个错误的做法是clicked信号关联了一个普通函数,在普通函数中创建新窗口的实例，同时调用show方法，现在想想实例的生命周期是有问题的，所以窗口一闪而过&lt;/li&gt;
&lt;/ul&gt;</summary><category term="pyqt"></category><category term="python"></category></entry><entry><title>pelican 如何添加404页面</title><link href="http://caimaoy.github.io/pelican-add-404-page.html" rel="alternate"></link><updated>2015-04-14T19:26:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-14:pelican-add-404-page.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;pelican 已经挂在了github上面了但是如何挂上一个404 页面&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;Title: Not Found
Status: hidden
Save_as: 404.html

&lt;span class="nt"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.qq.com/404/search_children.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;homePageUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.caimaoy.com&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;homePageName=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Back to Home Page&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;源码里面要说的几点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;添加Status: hidden这个元信息&lt;/li&gt;
&lt;li&gt;Save_as为404.html，这样的话就满足了github的要求&lt;/li&gt;
&lt;li&gt;挂上这一段js，出自我旁边的&lt;a href="http://www.qq.com/404/"&gt;鹅厂&lt;/a&gt;这样的事业还是要支持一下的&lt;/li&gt;
&lt;li&gt;最后看一看:&lt;a href="http://caimaoy.github.io/404/"&gt;效果图&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TODO&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;当然也是因为我没有找到pelican直接挂原始页面的办法，如果你知道下面disqus我&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;乱七八糟&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;我说了我今天要去跑步，不能再做一个颓废的胖纸了！！！&lt;/li&gt;
&lt;li&gt;另外今天在H亏成狗了，可以去天台了~&lt;/li&gt;
&lt;/ul&gt;</summary><category term="github"></category><category term="pelican"></category></entry><entry><title>python 判断windows系统是32位还是64位</title><link href="http://caimaoy.github.io/win32-or-win64-python.html" rel="alternate"></link><updated>2015-04-08T10:24:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-08:win32-or-win64-python.html</id><summary type="html">&lt;h3&gt;首先来看看错误方法：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;以下是在64位机器下使用32位python得到的结果&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [14]: sys.version
Out[14]: &amp;#39;2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)]&amp;#39;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;这里看到的其实是python的版本，而不是系统的版本&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [15]: platform.architecture()
Out[15]: (&amp;#39;32bit&amp;#39;, &amp;#39;WindowsPE&amp;#39;)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;这个运行的结果也是不正确的&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [16]: print sys.maxint
2147483647
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;数字是2**31-1的话就是32位(这是错误的！！！)&lt;/li&gt;
&lt;li&gt;数字式2**64-1的话就是64位(这也是错误的！！！)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面引述的方法也是不正确的，因为使用的是sys库&lt;/p&gt;
&lt;h3&gt;正确方法&lt;/h3&gt;
&lt;h4&gt;1. 通过环境变量进行判断&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;def is_64_windows():
    return &amp;#39;PROGRAMFILES(X86)&amp;#39; in os.environ
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;2. 通过注册表进行判断&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;aReg = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, \
&amp;quot;SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;存在即为64bits&lt;/li&gt;
&lt;li&gt;如果不存在会抛出异常，进行捕获判断返回32bits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;个人观点到此结束，如果有其他方法可以评论回复我，THX&lt;/p&gt;</summary><category term="python"></category><category term="windows"></category></entry><entry><title>python print</title><link href="http://caimaoy.github.io/python-print.html" rel="alternate"></link><updated>2015-04-07T13:58:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-07:python-print.html</id><summary type="html">&lt;p&gt;今天突然想到要聊一下这个话题  &lt;/p&gt;
&lt;p&gt;在实际的使用当中我们经常用到print来显示一些状态比如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [2]: print &amp;#39;caimaoy&amp;#39;
caimaoy

In [3]: print &amp;#39;caimaoy\n&amp;#39;
caimaoy


In [4]:
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;注意一下空行数&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;这里面有个隐藏的参数，就是print会在每次输出后再输出一个'\n'，那如果我们是读取的
文本的文件一行一行print操作，其实每一行会打印两个'\n', 其中一个来自文本，另外一
个来自print的默认参数，如果我们只想要一个'\n'如何解决这个问题？&lt;/p&gt;
&lt;h1&gt;解决方案&lt;/h1&gt;
&lt;h2&gt;1. 使用''.join把需要的内容拼接起来然后一次性打印&lt;/h2&gt;
&lt;p&gt;大概可以得到这样的效果：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [4]: a = [&amp;#39;caimaoy\n&amp;#39;, &amp;#39;caimaoy1\n&amp;#39;, &amp;#39;caimaoy3\n&amp;#39;]

In [5]: print &amp;#39;&amp;#39;.join(a)
caimaoy
caimaoy1
caimaoy3


In [6]:
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;2. 使用print中的参数end&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;In [6]: print (&amp;#39;caimaoy&amp;#39;, end=&amp;#39;&amp;#39;)
  File &amp;quot;&amp;lt;ipython-input-6-dfd4986b6077&amp;gt;&amp;quot;, line 1
    print (&amp;#39;caimaoy&amp;#39;, end=&amp;#39;&amp;#39;)
                         ^
SyntaxError: invalid syntax
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;但是不幸的是在python2中我们好像不能只是这样做，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;print_function&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;caimaoy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;caimaoy&lt;/span&gt;
&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;我们需要做&lt;pre&gt;from __future__ import print_function&lt;/pre&gt;这个操作可以正常使用。&lt;/p&gt;</summary><category term="python"></category></entry><entry><title>外链图片测试</title><link href="http://caimaoy.github.io/test-pic-vim-keyboard.html" rel="alternate"></link><updated>2015-04-03T18:36:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-03:test-pic-vim-keyboard.html</id><summary type="html">&lt;ul&gt;
&lt;li&gt;就是一个测试&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="test-pic-vim-keyboard" src="http://7xif3g.com1.z0.glb.clouddn.com/caimaoy_vim_keyboard.png" title="test-pic-vim-keyboard" /&gt;&lt;/p&gt;</summary><category term="test"></category><category term="picture"></category><category term="vim"></category></entry><entry><title>使用Pelican在Github上建立个人博客</title><link href="http://caimaoy.github.io/build-blog-on-github-with-pelican.html" rel="alternate"></link><updated>2015-04-01T09:51:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-04-01:build-blog-on-github-with-pelican.html</id><summary type="html">&lt;h1&gt;相关连接&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.xycoding.com/articles/2013/11/21/blog-create"&gt;基础篇&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.xycoding.com/articles/2013/11/22/blog-advance"&gt;进阶篇&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;有以上的链接我就不再赘述了，讲讲一些其他的坑&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;基础知识&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://python.org/"&gt;python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pages.github.com/"&gt;Github Pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;配置文件&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;这个应该是说得比较多的一部分了，因为使用windows(我也不想用！！！)不得不改动一下配置文件&lt;br /&gt;
重点修改如下&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Makefile&lt;/h2&gt;
&lt;p&gt;对于windows用户你可能要敢以下几件事&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;下载make.exe, 并且添加到环境变量中&lt;/li&gt;
&lt;li&gt;修改Makefile文件关键是一些路径，具体忘记是哪些了，你可以去看这个blog的&lt;a href="http://github.com/caimaoy"&gt;源代码&lt;/a&gt;对比一下&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;pelicanconfig.py&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;git: publish
    git push origin &lt;span class="k"&gt;$(&lt;/span&gt;GITHUB_PAGES_BRANCH&lt;span class="k"&gt;)&lt;/span&gt;
    ghp-import -b &lt;span class="k"&gt;$(&lt;/span&gt;GITHUB_PAGES_BRANCH&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;OUTPUTDIR&lt;span class="k"&gt;)&lt;/span&gt; -p
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;其中git的部分你懂就应该懂，说一下ghp-import&lt;br /&gt;
ghp-import 是用于分支发布的，也就是说你的源码是在一个分支，而生成的页面是在另外一个分支发布&lt;/p&gt;
&lt;h2&gt;ghp-import on Windows&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://docs.getpelican.com/en/latest/tips.html#publishing-to-github"&gt;Until ghp-import Pull Request #25 is accepted,you will need to install a custom build of ghp-import:&lt;/a&gt;  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install https://github.com/chevah/ghp-import/archive/win-support.zip
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;可以使用上面的pip安装&lt;br /&gt;
如果你安装不上可以先卸载&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip uninstall ghp-import
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;如果你无法用下面的方法安装，请下载&lt;a href="https://github.com/chevah/ghp-import/archive/win-support.zip"&gt;zip包&lt;/a&gt;后安装:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;python setup.py install
&lt;/pre&gt;&lt;/div&gt;</summary><category term="python"></category><category term="github"></category><category term="pelican"></category></entry><entry><title>关于我</title><link href="http://caimaoy.github.io/about-me.html" rel="alternate"></link><updated>2015-04-01T15:43:00+08:00</updated><author><name>caimaoy</name></author><id>tag:caimaoy.github.io,2015-01-01:about-me.html</id><summary type="html">&lt;h1&gt;一个在国人F3的打工仔&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;The Zen of Python, by Tim Peters&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Beautiful is better than ugly.&lt;/li&gt;
&lt;li&gt;Explicit is better than implicit.&lt;/li&gt;
&lt;li&gt;Simple is better than complex.&lt;/li&gt;
&lt;li&gt;Complex is better than complicated.&lt;/li&gt;
&lt;li&gt;Flat is better than nested.&lt;/li&gt;
&lt;li&gt;Sparse is better than dense.&lt;/li&gt;
&lt;li&gt;Readability counts.&lt;/li&gt;
&lt;li&gt;Special cases aren't special enough to break the rules.&lt;/li&gt;
&lt;li&gt;Although practicality beats purity.&lt;/li&gt;
&lt;li&gt;Errors should never pass silently.&lt;/li&gt;
&lt;li&gt;Unless explicitly silenced.&lt;/li&gt;
&lt;li&gt;In the face of ambiguity, refuse the temptation to guess.&lt;/li&gt;
&lt;li&gt;There should be one-- and preferably only one --obvious way to do it.&lt;/li&gt;
&lt;li&gt;Although that way may not be obvious at first unless you're Dutch.&lt;/li&gt;
&lt;li&gt;Now is better than never.&lt;/li&gt;
&lt;li&gt;Although never is often better than &lt;em&gt;right&lt;/em&gt; now.&lt;/li&gt;
&lt;li&gt;If the implementation is hard to explain, it's a bad idea.&lt;/li&gt;
&lt;li&gt;If the implementation is easy to explain, it may be a good idea.&lt;/li&gt;
&lt;li&gt;Namespaces are one honking great idea -- let's do more of those!&lt;/li&gt;
&lt;/ul&gt;</summary><category term="about-me"></category><category term="github"></category><category term="python"></category></entry></feed>