<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
     >

  <channel>
    <title>KDr2</title>
    <atom:link href="http://kdr2.net/service/feed/rss" rel="self" type="application/rss+xml" />
    <link>http://kdr2.net</link>
    <description>KDr2's Personal Site.</description>
    <lastBuildDate>Tue, 22 Dec 2009 02:15:47 +0000</lastBuildDate>

    <generator>KDr2's Persnal Site</generator>
    <language>en</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>


    <item>
      <title><![CDATA[Photo]]></title>

      <link>http://n.kdr2.net/post/17024155061</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Sat, 04 Feb 2012 18:20:21 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/17024155061</guid>
      <description>
        <![CDATA[<img src="http://30.media.tumblr.com/tumblr_lyueq0jsqG1qdz4c1o1_500.jpg"/><br/><br/>]]>
      </description>
      <content:encoded>
        <![CDATA[<img src="http://30.media.tumblr.com/tumblr_lyueq0jsqG1qdz4c1o1_500.jpg"/><br/><br/>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[ADIDAS FINALE MUNICH 2012 FOOTBALL]]></title>

      <link>http://n.kdr2.net/post/16974901258</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Fri, 03 Feb 2012 22:32:47 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16974901258</guid>
      <description>
        <![CDATA[<p><a class="tumblr_blog" href="http://wongwong.tumblr.com/post/16920731589/adidas-finale-munich-2012-football">wongwong</a>:</p>
<blockquote>
<p><img src="http://media.tumblr.com/tumblr_lyrtftstVT1qzw989.jpg"/></p>
<p>Official match ball for the 2012 UEFA Champions League Final on 19 May 2012 at the Allianz Arena in Munich, Germany. </p>
</blockquote>]]>
      </description>
      <content:encoded>
        <![CDATA[<p><a class="tumblr_blog" href="http://wongwong.tumblr.com/post/16920731589/adidas-finale-munich-2012-football">wongwong</a>:</p>
<blockquote>
<p><img src="http://media.tumblr.com/tumblr_lyrtftstVT1qzw989.jpg"/></p>
<p>Official match ball for the 2012 UEFA Champions League Final on 19 May 2012 at the Allianz Arena in Munich, Germany. </p>
</blockquote>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[PEP 380 is available (in hg default branch and 3.3a0).]]></title>

      <link>http://n.kdr2.net/post/16957128243</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Fri, 03 Feb 2012 11:18:20 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16957128243</guid>
      <description>
        <![CDATA[<p>I build a version from the hg default branch, and test <a href="http://www.python.org/dev/peps/pep-0380/">PEP380</a> with the code below.</p>
<!-- HTML generated using hilite.py -->
<div style="background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
<pre style="margin: 0; line-height: 125%;"><span style="color: #008000; font-weight: bold;">def</span> <span style="color: #0000ff;">gen1</span>(x):
    <span style="color: #008000; font-weight: bold;">while</span> x<span style="color: #666666;">>0</span>:
        <span style="color: #008000; font-weight: bold;">yield</span> x
        x<span style="color: #666666;">=</span>x<span style="color: #666666;">-1</span>

<span style="color: #008000; font-weight: bold;">def</span> <span style="color: #0000ff;">gen2</span>(x):
    <span style="color: #008000; font-weight: bold;">yield</span> <span style="color: #ba2121;">"start"</span>
    <span style="color: #008000; font-weight: bold;">yield</span> <span style="color: #008000; font-weight: bold;">from</span> <span style="color: #0000ff; font-weight: bold;">gen1</span><span style="border: 1px solid #FF0000;">(</span><span style="color: #0000ff; font-weight: bold;">x</span><span style="border: 1px solid #FF0000;">)</span>
    <span style="color: #008000; font-weight: bold;">yield</span> <span style="color: #ba2121;">"end"</span>

<span style="color: #008000; font-weight: bold;">import</span> <span style="color: #0000ff; font-weight: bold;">sys</span>
<span style="color: #008000; font-weight: bold;">print</span>(<span style="color: #ba2121;">""</span><span style="color: #666666;">.</span>join([<span style="color: #ba2121;">"Python Version:</span><span style="color: #bb6622; font-weight: bold;">\n</span><span style="color: #ba2121;">"</span>,
               sys<span style="color: #666666;">.</span>version,
               <span style="color: #ba2121;">"</span><span style="color: #bb6622; font-weight: bold;">\n\n</span><span style="color: #ba2121;">PEP 380 TEST:</span><span style="color: #bb6622; font-weight: bold;">\n</span><span style="color: #ba2121;">"</span>]))
[<span style="color: #008000; font-weight: bold;">print</span>(x) <span style="color: #008000; font-weight: bold;">for</span> x <span style="color: #aa22ff; font-weight: bold;">in</span> gen2(<span style="color: #666666;">3</span>)]
    
</pre>
</div>
<p>the output:</p>
<!-- HTML generated using hilite.py -->
<div style="background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
<pre style="margin: 0; line-height: 125%;">Python Version:
3.3.0a0 (default, Feb  3 2012, 10:38:09)
[GCC 4.6.2]

PEP 380 TEST:

start
3
2
1
end
</pre>
</div>
<p>It will free your own generator stacks maintenance. Will it be back ported to v2.x?</p>]]>
      </description>
      <content:encoded>
        <![CDATA[<p>I build a version from the hg default branch, and test <a href="http://www.python.org/dev/peps/pep-0380/">PEP380</a> with the code below.</p>
<!-- HTML generated using hilite.py -->
<div style="background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
<pre style="margin: 0; line-height: 125%;"><span style="color: #008000; font-weight: bold;">def</span> <span style="color: #0000ff;">gen1</span>(x):
    <span style="color: #008000; font-weight: bold;">while</span> x<span style="color: #666666;">>0</span>:
        <span style="color: #008000; font-weight: bold;">yield</span> x
        x<span style="color: #666666;">=</span>x<span style="color: #666666;">-1</span>

<span style="color: #008000; font-weight: bold;">def</span> <span style="color: #0000ff;">gen2</span>(x):
    <span style="color: #008000; font-weight: bold;">yield</span> <span style="color: #ba2121;">"start"</span>
    <span style="color: #008000; font-weight: bold;">yield</span> <span style="color: #008000; font-weight: bold;">from</span> <span style="color: #0000ff; font-weight: bold;">gen1</span><span style="border: 1px solid #FF0000;">(</span><span style="color: #0000ff; font-weight: bold;">x</span><span style="border: 1px solid #FF0000;">)</span>
    <span style="color: #008000; font-weight: bold;">yield</span> <span style="color: #ba2121;">"end"</span>

<span style="color: #008000; font-weight: bold;">import</span> <span style="color: #0000ff; font-weight: bold;">sys</span>
<span style="color: #008000; font-weight: bold;">print</span>(<span style="color: #ba2121;">""</span><span style="color: #666666;">.</span>join([<span style="color: #ba2121;">"Python Version:</span><span style="color: #bb6622; font-weight: bold;">\n</span><span style="color: #ba2121;">"</span>,
               sys<span style="color: #666666;">.</span>version,
               <span style="color: #ba2121;">"</span><span style="color: #bb6622; font-weight: bold;">\n\n</span><span style="color: #ba2121;">PEP 380 TEST:</span><span style="color: #bb6622; font-weight: bold;">\n</span><span style="color: #ba2121;">"</span>]))
[<span style="color: #008000; font-weight: bold;">print</span>(x) <span style="color: #008000; font-weight: bold;">for</span> x <span style="color: #aa22ff; font-weight: bold;">in</span> gen2(<span style="color: #666666;">3</span>)]
    
</pre>
</div>
<p>the output:</p>
<!-- HTML generated using hilite.py -->
<div style="background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
<pre style="margin: 0; line-height: 125%;">Python Version:
3.3.0a0 (default, Feb  3 2012, 10:38:09)
[GCC 4.6.2]

PEP 380 TEST:

start
3
2
1
end
</pre>
</div>
<p>It will free your own generator stacks maintenance. Will it be back ported to v2.x?</p>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA["Either write something worth reading or do something worth writing."]]></title>

      <link>http://n.kdr2.net/post/16914135748</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Thu, 02 Feb 2012 17:09:58 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16914135748</guid>
      <description>
        <![CDATA[“Either write something worth reading or do something worth writing.”<br/><br/> - <em>Benjamin Franklin</em>]]>
      </description>
      <content:encoded>
        <![CDATA[“Either write something worth reading or do something worth writing.”<br/><br/> - <em>Benjamin Franklin</em>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[China dived.]]></title>

      <link>http://n.kdr2.net/post/16897693112</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Thu, 02 Feb 2012 10:10:09 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16897693112</guid>
      <description>
        <![CDATA[<img src="http://26.media.tumblr.com/tumblr_lyqu0xSGN61qmuhy6o1_500.jpg"/><br/><br/><p>China dived.</p>]]>
      </description>
      <content:encoded>
        <![CDATA[<img src="http://26.media.tumblr.com/tumblr_lyqu0xSGN61qmuhy6o1_500.jpg"/><br/><br/><p>China dived.</p>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[8bitfuture:

Small car folds up to 149cm.
The Hiriko electric...]]></title>

      <link>http://n.kdr2.net/post/16895522880</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Thu, 02 Feb 2012 09:37:16 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16895522880</guid>
      <description>
        <![CDATA[<img src="http://30.media.tumblr.com/tumblr_lyiyuljOhK1qft3eko1_500.jpg"/><br/><br/><p><a href="http://8bitfuture.tumblr.com/post/16651198642/small-car-folds-up-to-149cm-the-hiriko-electric" class="tumblr_blog">8bitfuture</a>:</p>

<blockquote><p><strong>Small car folds up to 149cm.</strong></p>
<p>The Hiriko electric car is meant for small trips around an urban city, with its maximum speed of 59mph powered by four electric motors.</p>
<p>The car folds up at the press of a button to become only 149cm/59” long. That’s half the space a normal compact car needs. With no side doors on the car, the driver gets in and out the front, with the entire windscreen able to lift up.</p>
<p>When the car hits the market in 2013, it is expected to cost only US$16,500.</p></blockquote>]]>
      </description>
      <content:encoded>
        <![CDATA[<img src="http://30.media.tumblr.com/tumblr_lyiyuljOhK1qft3eko1_500.jpg"/><br/><br/><p><a href="http://8bitfuture.tumblr.com/post/16651198642/small-car-folds-up-to-149cm-the-hiriko-electric" class="tumblr_blog">8bitfuture</a>:</p>

<blockquote><p><strong>Small car folds up to 149cm.</strong></p>
<p>The Hiriko electric car is meant for small trips around an urban city, with its maximum speed of 59mph powered by four electric motors.</p>
<p>The car folds up at the press of a button to become only 149cm/59” long. That’s half the space a normal compact car needs. With no side doors on the car, the driver gets in and out the front, with the entire windscreen able to lift up.</p>
<p>When the car hits the market in 2013, it is expected to cost only US$16,500.</p></blockquote>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[Swansea City 1 - 1 Chelsea, 31st Jan 2012 PREMIER LEAGUE]]></title>

      <link>http://n.kdr2.net/post/16849420830</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Wed, 01 Feb 2012 10:23:00 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16849420830</guid>
      <description>
        <![CDATA[<img src="http://24.media.tumblr.com/tumblr_lyoxreOIU31qmuhy6o1_500.png"/><br/><br/><p><h3 class="r"><a href="http://www.premierleague.com/en-gb/clubs/profile.overview.html/chelsea" target="_blank"><span><span>Swansea City 1 - 1 </span></span><strong>Chelsea</strong></a>, <span>31st Jan 2012 PREMIER LEAGUE</span></h3></p>]]>
      </description>
      <content:encoded>
        <![CDATA[<img src="http://24.media.tumblr.com/tumblr_lyoxreOIU31qmuhy6o1_500.png"/><br/><br/><p><h3 class="r"><a href="http://www.premierleague.com/en-gb/clubs/profile.overview.html/chelsea" target="_blank"><span><span>Swansea City 1 - 1 </span></span><strong>Chelsea</strong></a>, <span>31st Jan 2012 PREMIER LEAGUE</span></h3></p>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[hilite.me: A tool converts your code snippets into pretty-printed HTML format, easily embeddable into blog posts, emails and websites.]]></title>

      <link>http://n.kdr2.net/post/16817800280</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Wed, 01 Feb 2012 10:22:31 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16817800280</guid>
      <description>
        <![CDATA[<a href="http://hilite.me/">hilite.me: A tool converts your code snippets into pretty-printed HTML format, easily embeddable into blog posts, emails and websites.</a>: <p>An example:</p>
<!-- HTML generated using hilite.me -->
<div style="background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
<table><tbody><tr><td>
<pre style="margin: 0; line-height: 125%;"> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15</pre>
</td>
<td>
<pre style="margin: 0; line-height: 125%;"><span style="color: #008000; font-weight: bold;">static</span> <span style="color: #008000; font-weight: bold;">struct</span> task_struct <span style="color: #666666;">*</span><span style="color: #0000ff;">next_tid</span>(<span style="color: #008000; font-weight: bold;">struct</span> task_struct <span style="color: #666666;">*</span>start)
{
	<span style="color: #008000; font-weight: bold;">struct</span> task_struct <span style="color: #666666;">*</span>pos <span style="color: #666666;">=</span> <span style="color: #008000;">NULL</span>;
	rcu_read_lock();
	<span style="color: #008000; font-weight: bold;">if</span> (pid_alive(start)) {
		pos <span style="color: #666666;">=</span> next_thread(start);
		<span style="color: #008000; font-weight: bold;">if</span> (thread_group_leader(pos))
			pos <span style="color: #666666;">=</span> <span style="color: #008000;">NULL</span>;
		<span style="color: #008000; font-weight: bold;">else</span>
			get_task_struct(pos);
	}
	rcu_read_unlock();
	put_task_struct(start);
	<span style="color: #008000; font-weight: bold;">return</span> pos;
}
</pre>
</td>
</tr></tbody></table></div>]]>
      </description>
      <content:encoded>
        <![CDATA[<a href="http://hilite.me/">hilite.me: A tool converts your code snippets into pretty-printed HTML format, easily embeddable into blog posts, emails and websites.</a>: <p>An example:</p>
<!-- HTML generated using hilite.me -->
<div style="background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
<table><tbody><tr><td>
<pre style="margin: 0; line-height: 125%;"> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15</pre>
</td>
<td>
<pre style="margin: 0; line-height: 125%;"><span style="color: #008000; font-weight: bold;">static</span> <span style="color: #008000; font-weight: bold;">struct</span> task_struct <span style="color: #666666;">*</span><span style="color: #0000ff;">next_tid</span>(<span style="color: #008000; font-weight: bold;">struct</span> task_struct <span style="color: #666666;">*</span>start)
{
	<span style="color: #008000; font-weight: bold;">struct</span> task_struct <span style="color: #666666;">*</span>pos <span style="color: #666666;">=</span> <span style="color: #008000;">NULL</span>;
	rcu_read_lock();
	<span style="color: #008000; font-weight: bold;">if</span> (pid_alive(start)) {
		pos <span style="color: #666666;">=</span> next_thread(start);
		<span style="color: #008000; font-weight: bold;">if</span> (thread_group_leader(pos))
			pos <span style="color: #666666;">=</span> <span style="color: #008000;">NULL</span>;
		<span style="color: #008000; font-weight: bold;">else</span>
			get_task_struct(pos);
	}
	rcu_read_unlock();
	put_task_struct(start);
	<span style="color: #008000; font-weight: bold;">return</span> pos;
}
</pre>
</td>
</tr></tbody></table></div>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[Node.js creator Ryan Dahl steps down]]></title>

      <link>http://n.kdr2.net/post/16815261783</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Wed, 01 Feb 2012 10:16:30 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16815261783</guid>
      <description>
        <![CDATA[<a href="https://groups.google.com/forum/#!topic/nodejs/hfajgpvGTLY">Node.js creator Ryan Dahl steps down</a>: <p><a class="tumblr_blog" href="http://log.julien.ponge.info/post/16813652790/node-js-creator-ryan-dahl-steps-down">jponge</a>:</p>
<blockquote>
<p>The project is far from dead, but he decided to leave and move on to other projects.</p>
<p>This is an important announcement though: Node.js is only 3 years old and the ecosystem is quite immature. It is still a bazaar of many competing modules, backwards compatibility is an issue, modules interoperability is not always smooth, and error messages in stack traces remain cryptic at times.</p>
<p>Node.js is not bad, but will it resist when the hype fades away? Time will tell.</p>
</blockquote>]]>
      </description>
      <content:encoded>
        <![CDATA[<a href="https://groups.google.com/forum/#!topic/nodejs/hfajgpvGTLY">Node.js creator Ryan Dahl steps down</a>: <p><a class="tumblr_blog" href="http://log.julien.ponge.info/post/16813652790/node-js-creator-ryan-dahl-steps-down">jponge</a>:</p>
<blockquote>
<p>The project is far from dead, but he decided to leave and move on to other projects.</p>
<p>This is an important announcement though: Node.js is only 3 years old and the ecosystem is quite immature. It is still a bazaar of many competing modules, backwards compatibility is an issue, modules interoperability is not always smooth, and error messages in stack traces remain cryptic at times.</p>
<p>Node.js is not bad, but will it resist when the hype fades away? Time will tell.</p>
</blockquote>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[发型的重要性]]></title>

      <link>http://n.kdr2.net/post/16759395266</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Mon, 30 Jan 2012 22:03:49 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16759395266</guid>
      <description>
        <![CDATA[<img src="http://27.media.tumblr.com/tumblr_lym72dJyN01qmuhy6o1_500.jpg"/><br/><br/><p>发型的重要性</p>]]>
      </description>
      <content:encoded>
        <![CDATA[<img src="http://27.media.tumblr.com/tumblr_lym72dJyN01qmuhy6o1_500.jpg"/><br/><br/><p>发型的重要性</p>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[SourceTree: A powerful Mac client for Git and Mercurial distributed version control systems.]]></title>

      <link>http://n.kdr2.net/post/16751972854</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Mon, 30 Jan 2012 15:30:00 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16751972854</guid>
      <description>
        <![CDATA[<a href="http://www.sourcetreeapp.com/">SourceTree: A powerful Mac client for Git and Mercurial distributed version control systems. </a>: <p>SourceTree strips away the complexity of DVCS and makes it usable for mere mortals.</p>]]>
      </description>
      <content:encoded>
        <![CDATA[<a href="http://www.sourcetreeapp.com/">SourceTree: A powerful Mac client for Git and Mercurial distributed version control systems. </a>: <p>SourceTree strips away the complexity of DVCS and makes it usable for mere mortals.</p>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[You Could Have Invented Monads! (And Maybe You Already Have.)]]></title>

      <link>http://n.kdr2.net/post/16681563170</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Mon, 30 Jan 2012 15:29:44 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[tumblr]]></category>

      <guid isPermaLink="false">http://n.kdr2.net/post/16681563170</guid>
      <description>
        <![CDATA[<a href="http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html">You Could Have Invented Monads! (And Maybe You Already Have.)</a>]]>
      </description>
      <content:encoded>
        <![CDATA[<a href="http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html">You Could Have Invented Monads! (And Maybe You Already Have.)</a>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[Ocampickle - Pickle/unPickle simple Python object in OCaml &mdash; KDr2&#39;s Personal Website]]></title>

      <link>http://kdr2.net/ocampickle.html</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Wed, 06 Jul 2011 17:32:00 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[article]]></category>

      <guid isPermaLink="false">http://kdr2.net/ocampickle.html</guid>
      <description>
        <![CDATA[<div class="section" id="ocampickle-pickle-unpickle-simple-python-object-in-ocaml">
<h1></h1>
<div class="section" id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
<p>Ocampickle is a samll library to Pickle/unPickle simple
Python object in <a class="reference external" href="http://caml.inria.fr/ocaml/index.en.html">OCaml</a>, corresponding to the
<strong>cPickle</strong> module in <a class="reference external" href="http://www.python.org">Python</a>.</p>
<p>You can get it from <a class="reference external" href="https://github.com/KDr2/ocampickle">https://github.com/KDr2/ocampickle</a> .</p>
</div>
<div class="section" id="install">
<h2>Install<a class="headerlink" href="#install" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>git clone git://github.com/KDr2/ocampickle.git</li>
<li>cd ocampickle</li>
<li>omake</li>
<li>omake install</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="getting-start">
<h2>Getting Start<a class="headerlink" href="#getting-start" title="Permalink to this headline">¶</a></h2>
<div class="highlight-ocaml"><pre>$ocaml
       Objective Caml version 3.12.0

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
# #load "nums.cma";;
# #require "ocampickle";;
/opt/local/lib/ocaml/site-lib/ocampickle: added to search path
/opt/local/lib/ocaml/site-lib/ocampickle/ocampickle.cma: loaded
# Ocampickle.loads;;
- : string -&gt; Ocampickle_type.t = &lt;fun&gt;
# let x=Ocampickle.loads "(lp1\nS'a'\naS'b'\na(dp2\nS'x'\nS'\\xe6\\xb5\\x8b\\xe8\\xaf\\x95'\np3\nsa.";;
val x : Ocampickle_type.t =
  Ocampickle_type.List
   [Ocampickle_type.String "a"; Ocampickle_type.String "b";
    Ocampickle_type.Dict &lt;abstr&gt;]
# Ocampickle_utils.pyprint x;;
["a","b",{"x":"测试",},]- : unit = ()
#...</pre>
</div>
</div>
<div class="section" id="simple-api">
<h2>Simple API<a class="headerlink" href="#simple-api" title="Permalink to this headline">¶</a></h2>
<div class="highlight-ocaml"><div class="highlight"><pre><span class="c">(* TYPE : Ocampickle_type.t *)</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span>
  <span class="o">|</span> <span class="nc">Dict</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span><span class="o">,</span> <span class="n">t</span><span class="o">)</span> <span class="nn">Hashtbl</span><span class="p">.</span><span class="n">t</span>  <span class="c">(* dict    *)</span>
  <span class="o">|</span> <span class="nc">List</span> <span class="k">of</span> <span class="n">t</span> <span class="kt">list</span>            <span class="c">(* list    *)</span>
  <span class="o">|</span> <span class="nc">Tuple</span> <span class="k">of</span> <span class="n">t</span> <span class="kt">list</span>           <span class="c">(* tuple   *)</span>
  <span class="o">|</span> <span class="nc">String</span> <span class="k">of</span> <span class="kt">string</span>          <span class="c">(* str     *)</span>
  <span class="o">|</span> <span class="nc">Unicode</span> <span class="k">of</span> <span class="kt">string</span>         <span class="c">(* unicode *)</span>
  <span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="kt">int</span>                <span class="c">(* int     *)</span>
  <span class="o">|</span> <span class="nc">Long</span> <span class="k">of</span> <span class="nn">Big_int</span><span class="p">.</span><span class="n">big_int</span>   <span class="c">(* int     *)</span>
  <span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="kt">float</span>            <span class="c">(* float   *)</span>
  <span class="o">|</span> <span class="nc">Bool</span> <span class="k">of</span> <span class="kt">bool</span>              <span class="c">(* bool    *)</span>
  <span class="o">|</span> <span class="nc">Object</span> <span class="k">of</span> <span class="kt">string</span>          <span class="c">(* object  *)</span>
  <span class="o">|</span> <span class="nc">Null</span>                      <span class="c">(* None    *)</span>
  <span class="o">|</span> <span class="nc">Ref</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="n">ref</span><span class="o">)</span>            <span class="c">(* Ref     *)</span><span class="o">;;</span>

<span class="c">(* pickle object *)</span>
<span class="k">val</span>  <span class="nn">Ocampickle</span><span class="p">.</span><span class="n">dumps</span> <span class="o">:</span> <span class="o">?</span><span class="n">proto</span><span class="o">:</span><span class="kt">int</span> <span class="o">-&gt;</span> <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="kt">string</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>

<span class="c">(* unpickle object *)</span>
<span class="k">val</span> <span class="nn">Ocampickle</span><span class="p">.</span><span class="n">loads</span> <span class="o">:</span> <span class="kt">string</span> <span class="o">-&gt;</span> <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>

<span class="c">(* print python object *)</span>
<span class="k">val</span> <span class="nn">Ocampickle_utils</span><span class="p">.</span><span class="n">pyoutput</span> <span class="o">:</span> <span class="n">out_channel</span> <span class="o">-&gt;</span> <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="kt">unit</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>
<span class="k">val</span> <span class="nn">Ocampickle_utils</span><span class="p">.</span><span class="n">pyprint</span> <span class="o">:</span>  <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="kt">unit</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>
</pre></div>
</div>
</div>
<div class="section" id="data-type-supported">
<h2>Data Type Supported<a class="headerlink" href="#data-type-supported" title="Permalink to this headline">¶</a></h2>
<p>Unfortunately, not all kinds of python data type are supported now,
here is a table demonstrating this below, and it will support all kind
of the data types (actually, all of the pickle opcode) later.</p>
<table border="1" class="docutils">
<caption>python data-type supported by ocampickle</caption>
<colgroup>
<col width="25%" />
<col width="25%" />
<col width="25%" />
<col width="25%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">type</th>
<th class="head">proto 0(default)</th>
<th class="head">proto 1</th>
<th class="head">proto 2</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>None</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>bool</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>int</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>long</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>-/-</td>
</tr>
<tr class="row-even"><td>float</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>string</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>unicode</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>tuple</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>list</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>dict</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>reference</td>
<td>pickle/-</td>
<td>pickle/-</td>
<td>pickle/-</td>
</tr>
<tr class="row-odd"><td>instance</td>
<td>-/-</td>
<td>-/-</td>
<td>-/-</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bug-report">
<h2>Bug Report<a class="headerlink" href="#bug-report" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>on github : <a class="reference external" href="https://github.com/KDr2/ocampickle">https://github.com/KDr2/ocampickle</a></li>
<li>email me  : killy.draw&lt;<tt class="docutils literal"><span class="pre">&#64;</span></tt>&gt;gmail.com</li>
</ul>
</div></blockquote>
</div>

<h2>Page(Article) Information / 页面(文章)信息:
  <a class="headerlink" href="#page-article-information" title="Permalink to this headline"></a>
</h2>
<ul class="simple">
  <li>Author : KDr2</li>
  <li>License : |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.en">
       Creative Commons BY-NC-ND 3.0
    </a> |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">
       CC3.0 : 自由转载-非商用-非衍生-保持署名
    </a> |
  </li>
  <li>Hosted on <a class="reference external" href="http://www.dreamhost.com/">DreamHost</a></li>
</ul>

</div>]]>
      </description>
      <content:encoded>
        <![CDATA[<div class="section" id="ocampickle-pickle-unpickle-simple-python-object-in-ocaml">
<h1></h1>
<div class="section" id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
<p>Ocampickle is a samll library to Pickle/unPickle simple
Python object in <a class="reference external" href="http://caml.inria.fr/ocaml/index.en.html">OCaml</a>, corresponding to the
<strong>cPickle</strong> module in <a class="reference external" href="http://www.python.org">Python</a>.</p>
<p>You can get it from <a class="reference external" href="https://github.com/KDr2/ocampickle">https://github.com/KDr2/ocampickle</a> .</p>
</div>
<div class="section" id="install">
<h2>Install<a class="headerlink" href="#install" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>git clone git://github.com/KDr2/ocampickle.git</li>
<li>cd ocampickle</li>
<li>omake</li>
<li>omake install</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="getting-start">
<h2>Getting Start<a class="headerlink" href="#getting-start" title="Permalink to this headline">¶</a></h2>
<div class="highlight-ocaml"><pre>$ocaml
       Objective Caml version 3.12.0

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
# #load "nums.cma";;
# #require "ocampickle";;
/opt/local/lib/ocaml/site-lib/ocampickle: added to search path
/opt/local/lib/ocaml/site-lib/ocampickle/ocampickle.cma: loaded
# Ocampickle.loads;;
- : string -&gt; Ocampickle_type.t = &lt;fun&gt;
# let x=Ocampickle.loads "(lp1\nS'a'\naS'b'\na(dp2\nS'x'\nS'\\xe6\\xb5\\x8b\\xe8\\xaf\\x95'\np3\nsa.";;
val x : Ocampickle_type.t =
  Ocampickle_type.List
   [Ocampickle_type.String "a"; Ocampickle_type.String "b";
    Ocampickle_type.Dict &lt;abstr&gt;]
# Ocampickle_utils.pyprint x;;
["a","b",{"x":"测试",},]- : unit = ()
#...</pre>
</div>
</div>
<div class="section" id="simple-api">
<h2>Simple API<a class="headerlink" href="#simple-api" title="Permalink to this headline">¶</a></h2>
<div class="highlight-ocaml"><div class="highlight"><pre><span class="c">(* TYPE : Ocampickle_type.t *)</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span>
  <span class="o">|</span> <span class="nc">Dict</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span><span class="o">,</span> <span class="n">t</span><span class="o">)</span> <span class="nn">Hashtbl</span><span class="p">.</span><span class="n">t</span>  <span class="c">(* dict    *)</span>
  <span class="o">|</span> <span class="nc">List</span> <span class="k">of</span> <span class="n">t</span> <span class="kt">list</span>            <span class="c">(* list    *)</span>
  <span class="o">|</span> <span class="nc">Tuple</span> <span class="k">of</span> <span class="n">t</span> <span class="kt">list</span>           <span class="c">(* tuple   *)</span>
  <span class="o">|</span> <span class="nc">String</span> <span class="k">of</span> <span class="kt">string</span>          <span class="c">(* str     *)</span>
  <span class="o">|</span> <span class="nc">Unicode</span> <span class="k">of</span> <span class="kt">string</span>         <span class="c">(* unicode *)</span>
  <span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="kt">int</span>                <span class="c">(* int     *)</span>
  <span class="o">|</span> <span class="nc">Long</span> <span class="k">of</span> <span class="nn">Big_int</span><span class="p">.</span><span class="n">big_int</span>   <span class="c">(* int     *)</span>
  <span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="kt">float</span>            <span class="c">(* float   *)</span>
  <span class="o">|</span> <span class="nc">Bool</span> <span class="k">of</span> <span class="kt">bool</span>              <span class="c">(* bool    *)</span>
  <span class="o">|</span> <span class="nc">Object</span> <span class="k">of</span> <span class="kt">string</span>          <span class="c">(* object  *)</span>
  <span class="o">|</span> <span class="nc">Null</span>                      <span class="c">(* None    *)</span>
  <span class="o">|</span> <span class="nc">Ref</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="n">ref</span><span class="o">)</span>            <span class="c">(* Ref     *)</span><span class="o">;;</span>

<span class="c">(* pickle object *)</span>
<span class="k">val</span>  <span class="nn">Ocampickle</span><span class="p">.</span><span class="n">dumps</span> <span class="o">:</span> <span class="o">?</span><span class="n">proto</span><span class="o">:</span><span class="kt">int</span> <span class="o">-&gt;</span> <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="kt">string</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>

<span class="c">(* unpickle object *)</span>
<span class="k">val</span> <span class="nn">Ocampickle</span><span class="p">.</span><span class="n">loads</span> <span class="o">:</span> <span class="kt">string</span> <span class="o">-&gt;</span> <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>

<span class="c">(* print python object *)</span>
<span class="k">val</span> <span class="nn">Ocampickle_utils</span><span class="p">.</span><span class="n">pyoutput</span> <span class="o">:</span> <span class="n">out_channel</span> <span class="o">-&gt;</span> <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="kt">unit</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>
<span class="k">val</span> <span class="nn">Ocampickle_utils</span><span class="p">.</span><span class="n">pyprint</span> <span class="o">:</span>  <span class="nn">Ocampickle_type</span><span class="p">.</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="kt">unit</span> <span class="o">=</span> <span class="o">&lt;</span><span class="k">fun</span><span class="o">&gt;</span>
</pre></div>
</div>
</div>
<div class="section" id="data-type-supported">
<h2>Data Type Supported<a class="headerlink" href="#data-type-supported" title="Permalink to this headline">¶</a></h2>
<p>Unfortunately, not all kinds of python data type are supported now,
here is a table demonstrating this below, and it will support all kind
of the data types (actually, all of the pickle opcode) later.</p>
<table border="1" class="docutils">
<caption>python data-type supported by ocampickle</caption>
<colgroup>
<col width="25%" />
<col width="25%" />
<col width="25%" />
<col width="25%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">type</th>
<th class="head">proto 0(default)</th>
<th class="head">proto 1</th>
<th class="head">proto 2</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>None</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>bool</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>int</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>long</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>-/-</td>
</tr>
<tr class="row-even"><td>float</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>string</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>unicode</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>tuple</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>list</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-odd"><td>dict</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
<td>pickle/unpickle</td>
</tr>
<tr class="row-even"><td>reference</td>
<td>pickle/-</td>
<td>pickle/-</td>
<td>pickle/-</td>
</tr>
<tr class="row-odd"><td>instance</td>
<td>-/-</td>
<td>-/-</td>
<td>-/-</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="bug-report">
<h2>Bug Report<a class="headerlink" href="#bug-report" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>on github : <a class="reference external" href="https://github.com/KDr2/ocampickle">https://github.com/KDr2/ocampickle</a></li>
<li>email me  : killy.draw&lt;<tt class="docutils literal"><span class="pre">&#64;</span></tt>&gt;gmail.com</li>
</ul>
</div></blockquote>
</div>

<h2>Page(Article) Information / 页面(文章)信息:
  <a class="headerlink" href="#page-article-information" title="Permalink to this headline"></a>
</h2>
<ul class="simple">
  <li>Author : KDr2</li>
  <li>License : |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.en">
       Creative Commons BY-NC-ND 3.0
    </a> |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">
       CC3.0 : 自由转载-非商用-非衍生-保持署名
    </a> |
  </li>
  <li>Hosted on <a class="reference external" href="http://www.dreamhost.com/">DreamHost</a></li>
</ul>

</div>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[PYC文件格式分析 &mdash; KDr2&#39;s Personal Website]]></title>

      <link>http://kdr2.net/blog/pyc_format.html</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Fri, 24 Dec 2010 10:05:00 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[article]]></category>

      <guid isPermaLink="false">http://kdr2.net/blog/pyc_format.html</guid>
      <description>
        <![CDATA[<div class="section" id="pyc">
<h1></h1>
<div class="section" id="id2">
<h2>PYC文件简介<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<p>不说废话,这里说的pyc文件就是 <a class="reference external" href="http://www.python.org">Python</a> 程序编译后得到的字节码文件
(py-&gt;pyc).</p>
</div>
<div class="section" id="id3">
<h2>基本格式<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h2>
<p>pyc文件一般由3个部分组成:</p>
<ul class="simple">
<li>最开始4个字节是一个Maigc int, 标识此pyc的版本信息, 不同的版本的 Magic
都在 <tt class="docutils literal"><span class="pre">Python/import.c</span></tt> 内定义</li>
<li>接下来四个字节还是个int,是pyc产生的时间(1970.01.01到产生pyc时候的秒
数)</li>
<li>接下来是个序列化了的 PyCodeObject(此结构在 <tt class="docutils literal"><span class="pre">Include/code.h</span></tt> 内定
义),序列化方法在 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内定义</li>
</ul>
<p>前两个字段的读写很简单,接下来咱们主要看一下 PyCodeObject 的序列化过程,
由于 PyCodeObject 内还有其他很多类型的 PyObject, 所以咱们从一般的
PyObject 的序列化开始看起:</p>
</div>
<div class="section" id="pyobject">
<h2>PyObject的序列化<a class="headerlink" href="#pyobject" title="Permalink to this headline">¶</a></h2>
<p>PyObject的序列化在 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内实现, 一般是先写入一个 byte
来标识此 PyObject 的类型, 每种 PyObject 对应的类型也在
<tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内定义:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//Python/marshal.c:22</span>
<span class="cp">#define TYPE_NULL               &#39;0&#39;</span>
<span class="cp">#define TYPE_NONE               &#39;N&#39;</span>
<span class="cp">#define TYPE_FALSE              &#39;F&#39;</span>
<span class="cp">#define TYPE_TRUE               &#39;T&#39;</span>
<span class="cp">#define TYPE_STOPITER           &#39;S&#39;</span>
<span class="cp">#define TYPE_ELLIPSIS           &#39;.&#39;</span>
<span class="cp">#define TYPE_INT                &#39;i&#39;</span>
<span class="cp">#define TYPE_INT64              &#39;I&#39;</span>
<span class="cp">#define TYPE_FLOAT              &#39;f&#39;</span>
<span class="cp">#define TYPE_BINARY_FLOAT       &#39;g&#39;</span>
<span class="cp">#define TYPE_COMPLEX            &#39;x&#39;</span>
<span class="cp">#define TYPE_BINARY_COMPLEX     &#39;y&#39;</span>
<span class="cp">#define TYPE_LONG               &#39;l&#39;</span>
<span class="cp">#define TYPE_STRING             &#39;s&#39;</span>
<span class="cp">#define TYPE_INTERNED           &#39;t&#39;</span>
<span class="cp">#define TYPE_STRINGREF          &#39;R&#39;</span>
<span class="cp">#define TYPE_TUPLE              &#39;(&#39;</span>
<span class="cp">#define TYPE_LIST               &#39;[&#39;</span>
<span class="cp">#define TYPE_DICT               &#39;{&#39;</span>
<span class="cp">#define TYPE_CODE               &#39;c&#39;</span>
<span class="cp">#define TYPE_UNICODE            &#39;u&#39;</span>
<span class="cp">#define TYPE_UNKNOWN            &#39;?&#39;</span>
<span class="cp">#define TYPE_SET                &#39;&lt;&#39;</span>
<span class="cp">#define TYPE_FROZENSET          &#39;&gt;&#39;</span>
</pre></div>
</div>
<p>之后是 PyObject 的具体数据内容, 变长的对象(str, tuple, list 等)往往还
包含了一个 4 bytes 的 len, 比如 PyIntObject 的存储可能是这样的:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>&#8216;i&#8217;</td>
<td>4 bytes int</td>
</tr>
<tr class="row-even"><td>&#8216;I&#8217;</td>
<td>8 bytes int</td>
</tr>
</tbody>
</table>
<p>而 PyStringObject 的存储是这样的:</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>&#8216;s&#8217;</td>
<td>4 bytes length</td>
<td>length bytes content(char[])</td>
</tr>
</tbody>
</table>
<p>PyTupleObject 和 PyListObject 的存储分别是:</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>&#8216;(&#8216;</td>
<td>4 bytes length</td>
<td>length 个 PyObject</td>
</tr>
<tr class="row-even"><td>&#8216;[&#8216;</td>
<td>4 bytes length</td>
<td>length 个 PyObject</td>
</tr>
</tbody>
</table>
<p>各种 PyObject 如何序列化,哪些内容被参与了序列化, 可以参看
<tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内的函数 <tt class="docutils literal"><span class="pre">w_object</span></tt> 函数, 接下来咱们着重看下前
面提到的 PyCodeObject 的序列化:</p>
</div>
<div class="section" id="pycodeobject">
<h2>PyCodeObject 的序列化<a class="headerlink" href="#pycodeobject" title="Permalink to this headline">¶</a></h2>
<p>结构体 PyCodeObject 在 <tt class="docutils literal"><span class="pre">Include/code.h</span></tt> 中定义如下:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//Include/code.h</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">PyObject_HEAD</span>
    <span class="kt">int</span> <span class="n">co_argcount</span><span class="p">;</span>        <span class="cm">/* #arguments, except *args */</span>
    <span class="kt">int</span> <span class="n">co_nlocals</span><span class="p">;</span>     <span class="cm">/* #local variables */</span>
    <span class="kt">int</span> <span class="n">co_stacksize</span><span class="p">;</span>       <span class="cm">/* #entries needed for evaluation stack */</span>
    <span class="kt">int</span> <span class="n">co_flags</span><span class="p">;</span>       <span class="cm">/* CO_..., see below */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_code</span><span class="p">;</span>      <span class="cm">/* instruction opcodes */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_consts</span><span class="p">;</span>    <span class="cm">/* list (constants used) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_names</span><span class="p">;</span>     <span class="cm">/* list of strings (names used) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_varnames</span><span class="p">;</span>  <span class="cm">/* tuple of strings (local variable names) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_freevars</span><span class="p">;</span>  <span class="cm">/* tuple of strings (free variable names) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_cellvars</span><span class="p">;</span>      <span class="cm">/* tuple of strings (cell variable names) */</span>
    <span class="cm">/* The rest doesn&#39;t count for hash/cmp */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_filename</span><span class="p">;</span>  <span class="cm">/* string (where it was loaded from) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_name</span><span class="p">;</span>      <span class="cm">/* string (name, for reference) */</span>
    <span class="kt">int</span> <span class="n">co_firstlineno</span><span class="p">;</span>     <span class="cm">/* first source line number */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_lnotab</span><span class="p">;</span>    <span class="cm">/* string (encoding addr&lt;-&gt;lineno mapping) See</span>
<span class="cm">                   Objects/lnotab_notes.txt for details. */</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">co_zombieframe</span><span class="p">;</span>     <span class="cm">/* for optimization only (see frameobject.c) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_weakreflist</span><span class="p">;</span>   <span class="cm">/* to support weakrefs to code objects */</span>
<span class="p">}</span> <span class="n">PyCodeObject</span><span class="p">;</span>
</pre></div>
</div>
<p>我们再看 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 里面的 <tt class="docutils literal"><span class="pre">w_object</span></tt> 函数,从中找出写
PyCodeObject 的部分如下:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//...</span>
<span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">PyCode_Check</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">PyCodeObject</span> <span class="o">*</span><span class="n">co</span> <span class="o">=</span> <span class="p">(</span><span class="n">PyCodeObject</span> <span class="o">*</span><span class="p">)</span><span class="n">v</span><span class="p">;</span>
    <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_CODE</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_argcount</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_nlocals</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_stacksize</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_flags</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_code</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_consts</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_names</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_varnames</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_freevars</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_cellvars</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_filename</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_name</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_firstlineno</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_lnotab</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//...</span>
</pre></div>
</div>
<p>根据上面两段代码,我们很容易就能看到 PyCodeObject 里哪些字段需要参数序
列化了,我们就挨个解释下需要序列化的字段们:</p>
<ul class="simple">
<li>co_argcount : code需要的位置参数个数,不包括变长参数(*args和**kwargs)</li>
<li>co_nlocals : code内所有的局部变量的个数,包括所有参数</li>
<li>co_stacksize : code段运行时所需要的最大栈深度</li>
<li>co_flags : 一些标识位,也在code.h里定义,注释很清楚,比如
CO_NOFREE(64) 表示此 PyCodeObject 内无 freevars 和 cellvars 等</li>
<li>co_code : PyStringObject(&#8216;s&#8217;), code对应的字节码(参看
<tt class="docutils literal"><span class="pre">Include/opcode.h</span></tt> 以及此文后续章节)</li>
<li>co_consts : 所有常量组成的tuple</li>
<li>co_names : code所用的到符号表, tuple类型,元素是字符串</li>
<li>co_varnames : code所用到的局部变量名, tuple类型, 元素是
PyStringObject(&#8216;s/t/R&#8217;)</li>
<li>co_freevars : code所用到的freevar的变量名,tuple类型, 元素是
PyStringObject(&#8216;s/t/R&#8217;)</li>
<li>co_cellvars : code所用到的cellvar的变量名,tuple类型, 元素是
PyStringObject(&#8216;s/t/R&#8217;)</li>
<li>co_filename : PyStringObject(&#8216;s&#8217;), 此code对应的py文件</li>
<li>co_name : 此code的名称</li>
<li>co_firstlineno : 此code对应的py文件里的第一行的行号</li>
<li>co_lnotab : PyStringObject(&#8216;s&#8217;),指令与行号的对应表</li>
</ul>
<p>在 Python 代码中,每个作用域(<em>或者叫block或者名字空间?</em>)对应一个
PyCodeObject 对象, 所以会出现嵌套: 比如 一个 module 类 定义了 N 个
class, 每个 class 内又定义了 M 个方法. 每个 <strong>子作用域</strong> 对应的
PyCodeObject 会出现在它的 <strong>父作用域</strong> 对应的 PyCodeObject 的
co_consts 字段里.</p>
<p>接下来用个例子对上面的某些字段做个说明, 比如下面的python代码</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#test.py</span>
<span class="kn">import</span> <span class="nn">struct</span>

<span class="k">def</span> <span class="nf">abc</span><span class="p">(</span><span class="n">c</span><span class="p">):</span>
    <span class="n">a</span><span class="o">=</span><span class="mi">1</span>
    <span class="n">b</span><span class="o">=</span><span class="mi">2</span>
    <span class="k">return</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s">&quot;S&quot;</span><span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="o">+</span><span class="n">c</span><span class="p">)</span>

<span class="n">var_a</span><span class="o">=</span><span class="s">&quot;abc&quot;</span>
<span class="n">var_b</span><span class="o">=</span><span class="p">{</span><span class="n">var_a</span><span class="p">:</span><span class="mi">123</span><span class="p">,</span><span class="s">&quot;sec_key&quot;</span><span class="p">:</span><span class="n">abc</span><span class="p">}</span>
</pre></div>
</div>
<p>它编译后对应的 pyc 在 <tt class="docutils literal"><span class="pre">magic</span></tt> 和 <tt class="docutils literal"><span class="pre">time</span></tt> 后就放着一个 PyCodeObject
对象, 这个对象的个字段指如下</p>
<table border="1" class="docutils">
<caption><strong>test.py对应PyCodeObject中各字段的值</strong></caption>
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">字段</th>
<th class="head">值</th>
<th class="head">注释</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>co_argcount</td>
<td>0</td>
<td>模块没有参数</td>
</tr>
<tr class="row-odd"><td>co_nlocals</td>
<td>0</td>
<td>模块没有局部变量</td>
</tr>
<tr class="row-even"><td>co_stacksize</td>
<td>3</td>
<td>栈最大尺寸</td>
</tr>
<tr class="row-odd"><td>co_flags</td>
<td>64</td>
<td>CO_NOFREE</td>
</tr>
<tr class="row-even"><td>co_code</td>
<td>&#8216;dx00x00d...&#8217;</td>
<td>字节码序列</td>
</tr>
<tr class="row-odd"><td>co_consts</td>
<td>(-1, None, another-code-obj...)</td>
<td>所有常量,包括模块里的
function,method</td>
</tr>
<tr class="row-even"><td>co_names</td>
<td>(&#8216;struct&#8217;, &#8216;abc&#8217;, &#8216;var_a&#8217;, &#8216;var_b&#8217;)</td>
<td>此作用域内用到的所
有符号</td>
</tr>
<tr class="row-odd"><td>co_varnames</td>
<td>()</td>
<td>局部变量名(模块没有局部变量)</td>
</tr>
<tr class="row-even"><td>co_freevars</td>
<td>()</td>
<td>freevars</td>
</tr>
<tr class="row-odd"><td>co_cellvars</td>
<td>()</td>
<td>cellvars</td>
</tr>
<tr class="row-even"><td>co_filename</td>
<td>test.py</td>
<td>源码文件名</td>
</tr>
<tr class="row-odd"><td>co_name</td>
<td>&#8216;&lt;module&gt;&#8217;</td>
<td>code名字,模块名都是&lt;module&gt;,class是类名,func是
函数名</td>
</tr>
<tr class="row-even"><td>co_firstlineno</td>
<td>3</td>
<td>此code对应作用域的第一行的行号</td>
</tr>
<tr class="row-odd"><td>co_lnotab</td>
<td>&#8216;x0cx02tx05x06x01&#8217;</td>
<td>行号表</td>
</tr>
</tbody>
</table>
<p>这其中的 <strong>co_consts</strong> 里面的第三个元素是function abc的PyCodeObject,
我们来看下function abc的code的各字段:</p>
<table border="1" class="docutils">
<caption><strong>function abc 对应PyCodeObject中各字段的值</strong></caption>
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">字段</th>
<th class="head">值</th>
<th class="head">注释</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>co_argcount</td>
<td>1</td>
<td>1个参数c</td>
</tr>
<tr class="row-odd"><td>co_nlocals</td>
<td>3</td>
<td>1个参数c, 两个局部变量a,b</td>
</tr>
<tr class="row-even"><td>co_stacksize</td>
<td>4</td>
<td>栈最大尺寸</td>
</tr>
<tr class="row-odd"><td>co_flags</td>
<td>67</td>
<td>CO_OPTIMIZATION | CO_NEWLOCALS | CO_NOFREE</td>
</tr>
<tr class="row-even"><td>co_code</td>
<td>&#8216;dx01x00}...&#8217;</td>
<td>字节码序列</td>
</tr>
<tr class="row-odd"><td>co_consts</td>
<td>(None, 1, 2, &#8216;S&#8217;)</td>
<td>函数里用到的所有常量</td>
</tr>
<tr class="row-even"><td>co_names</td>
<td>(&#8216;struct&#8217;, &#8216;pack&#8217;)</td>
<td>此作用域内用到的所有符号</td>
</tr>
<tr class="row-odd"><td>co_varnames</td>
<td>(&#8216;c&#8217;, &#8216;a&#8217;, &#8216;b&#8217;)</td>
<td>局部变量名</td>
</tr>
<tr class="row-even"><td>co_freevars</td>
<td>()</td>
<td>freevars</td>
</tr>
<tr class="row-odd"><td>co_cellvars</td>
<td>()</td>
<td>cellvars</td>
</tr>
<tr class="row-even"><td>co_filename</td>
<td>test.py</td>
<td>源码文件名</td>
</tr>
<tr class="row-odd"><td>co_name</td>
<td>&#8216;abc&#8217;</td>
<td>code名字,func是函数名</td>
</tr>
<tr class="row-even"><td>co_firstlineno</td>
<td>5</td>
<td>此code对应作用域的第一行的行号</td>
</tr>
<tr class="row-odd"><td>co_lnotab</td>
<td>&#8216;x00x01x06x01x06x01&#8217;</td>
<td>行号表</td>
</tr>
</tbody>
</table>
<div class="section" id="test-py-test-pyc">
<h3>图解 test.py 与 test.pyc 的结构关系<a class="headerlink" href="#test-py-test-pyc" title="Permalink to this headline">¶</a></h3>
<br /><br /><img alt="../_images/pyc_format_example_0.png" src="../_images/pyc_format_example_0.png" style="width: 800px; height: 1057px;" />
</div>
<div class="section" id="co-freevars-co-cellvars">
<h3>co_freevars 与 co_cellvars<a class="headerlink" href="#co-freevars-co-cellvars" title="Permalink to this headline">¶</a></h3>
<p>这两个字段是给 Closure 准备的(<em>Python里没有真正的Closure</em>),通俗的说就
是函数嵌套的时候用的到,比如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">outter</span><span class="p">(</span><span class="n">o1</span><span class="p">,</span><span class="n">o2</span><span class="p">):</span>
    <span class="n">fc1</span><span class="o">=</span><span class="n">o1</span><span class="o">+</span><span class="n">o2</span>
    <span class="n">fc2</span><span class="o">=</span><span class="n">o1</span><span class="o">*</span><span class="n">o2</span>
    <span class="k">def</span> <span class="nf">inner</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
        <span class="k">return</span> <span class="p">(</span><span class="n">fc1</span><span class="o">+</span><span class="n">fc2</span><span class="p">)</span><span class="o">*</span><span class="n">i</span>
</pre></div>
</div>
<ul class="simple">
<li>对于 outter 函数来说,他的局部变量 fc1 和 fc2 被它内部嵌套的函数所引
用,则 fc1 和 fc2 变成它的 <strong>cellvars</strong> 而不是局部变量 varnames</li>
<li>对于 inner 函数, fc1 和 fc2 既不是局部变量也不是全局变量,他引用自外
层函数, 则 fc1 和 fc2 是 inner 的 <strong>freevars</strong></li>
</ul>
</div>
<div class="section" id="pystringobject">
<h3>PyStringObject 的序列化<a class="headerlink" href="#pystringobject" title="Permalink to this headline">¶</a></h3>
<p>通过前面的介绍,你可能会发现PyCodeObject里面的用到str(&#8216;s&#8217;)类型的地方很
多,什么co_consts啊,co_names,co_varnames,co_freevars,co_cellvars等等都
是str的tuple,里面的str重复的也比较多,要是一股脑这么写进去可能会占用很
大空间,于是w_object里对PyStringObject的序列化又多加了两种类型:</p>
<ul class="simple">
<li>&#8216;t&#8217; : interned-string, 暂时可能简单理解为 pyc 里回重复出现的 str, 这
个类型就是简单的把 str 的类型 &#8216;s&#8217; 改成 &#8216;t&#8217; 了,后面还是跟
length(4bytes) 和 content(char[])</li>
<li>&#8216;R&#8217; : 指向 interned-string 的字符串引用, &#8216;R&#8217;后面跟4个 bytea 的引用序
号</li>
</ul>
<p>具体看 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内 <tt class="docutils literal"><span class="pre">w_object</span></tt> 的相关实现:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//...</span>
<span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">PyString_CheckExact</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span> <span class="o">&amp;&amp;</span> <span class="n">PyString_CHECK_INTERNED</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">PyObject</span> <span class="o">*</span><span class="n">o</span> <span class="o">=</span> <span class="n">PyDict_GetItem</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span><span class="p">,</span> <span class="n">v</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">o</span><span class="p">)</span> <span class="p">{</span>
            <span class="kt">long</span> <span class="n">w</span> <span class="o">=</span> <span class="n">PyInt_AsLong</span><span class="p">(</span><span class="n">o</span><span class="p">);</span>
            <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_STRINGREF</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
            <span class="n">w_long</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
            <span class="k">goto</span> <span class="n">exit</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span> <span class="p">{</span>
            <span class="kt">int</span> <span class="n">ok</span><span class="p">;</span>
            <span class="n">o</span> <span class="o">=</span> <span class="n">PyInt_FromSsize_t</span><span class="p">(</span><span class="n">PyDict_Size</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span><span class="p">));</span>
            <span class="n">ok</span> <span class="o">=</span> <span class="n">o</span> <span class="o">&amp;&amp;</span>
                 <span class="n">PyDict_SetItem</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">o</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="n">Py_XDECREF</span><span class="p">(</span><span class="n">o</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ok</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">p</span><span class="o">-&gt;</span><span class="n">depth</span><span class="o">--</span><span class="p">;</span>
                <span class="n">p</span><span class="o">-&gt;</span><span class="n">error</span> <span class="o">=</span> <span class="n">WFERR_UNMARSHALLABLE</span><span class="p">;</span>
                <span class="k">return</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_INTERNED</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_STRING</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">n</span> <span class="o">=</span> <span class="n">PyString_GET_SIZE</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="n">INT_MAX</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/* huge strings are not supported */</span>
        <span class="n">p</span><span class="o">-&gt;</span><span class="n">depth</span><span class="o">--</span><span class="p">;</span>
        <span class="n">p</span><span class="o">-&gt;</span><span class="n">error</span> <span class="o">=</span> <span class="n">WFERR_UNMARSHALLABLE</span><span class="p">;</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">w_long</span><span class="p">((</span><span class="kt">long</span><span class="p">)</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_string</span><span class="p">(</span><span class="n">PyString_AS_STRING</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//...</span>
</pre></div>
</div>
</div>
<div class="section" id="id4">
<h3>行号对照表<a class="headerlink" href="#id4" title="Permalink to this headline">¶</a></h3>
<p>co_lnotab可以看做是(字节码在co_opcode中的index增量(1 byte),对应的源码
的行号增量(1-bytes))顺次串成的的字节数组(字符串).</p>
</div>
</div>
<div class="section" id="co-code-pythonopcode">
<h2>字段 co_code 与 Python的OPCODE<a class="headerlink" href="#co-code-pythonopcode" title="Permalink to this headline">¶</a></h2>
<p>PyCodeObject 的 co_code 字段就是 python opcode 组成的序列, 具体有哪些
opcode可以参看 <tt class="docutils literal"><span class="pre">Include/opcode.h</span></tt> , 这里面有些opcode有参数,有些没有
参数, 从opcode.h内的代码段:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="cp">#define HAVE_ARGUMENT 90  </span><span class="cm">/* Opcodes from here have an argument: */</span><span class="cp"></span>
<span class="c1">//...</span>
<span class="cp">#define HAS_ARG(op) ((op) &gt;= HAVE_ARGUMENT)</span>
</pre></div>
</div>
<p>可以看出,大于等与90的opcode是有参数的, 有参数的opcode的参数是两个
unsigned byte, 第一个是操作数, 第二个目前固定为0x00但是不能省略,举例来
说,我要把当前code的co_consts里的第二个常量(index是1)载入到栈顶,则对应
的opcode序列为: <tt class="docutils literal"><span class="pre">|LOAD_CONST|0x01|0x00|</span></tt> ,也就是 <tt class="docutils literal"><span class="pre">'0x640x010x00'</span></tt></p>
<p>其他的opcode大都类似,主要是对函数调用栈以及co_consts, co_varnames,
co_freevars, co_cellvars的操作, 还有些BUILD_CLASS, BUILD_MAP,
BUILD_LIST, BUILD_TUPLE, BUILD_SLICE, MAKE_FUNCTION, MAKE_CLOSURE 等构
建对象的特殊指令.</p>
<p>有参数的 opcode 的参数的参数大多时候是个 index, 比如 <tt class="docutils literal"><span class="pre">LOAD_CONST</span> <span class="pre">1</span></tt>
的 1 就是个 index, 表示把当前 <tt class="docutils literal"><span class="pre">PyCodeObject.co_consts[1]</span></tt> 这个常量载
入到栈顶, <tt class="docutils literal"><span class="pre">LOAD_FAST</span> <span class="pre">2</span></tt> 则是把 <tt class="docutils literal"><span class="pre">PyCodeObject.co_varnames[2]</span></tt> 这个
局部变量载入到栈顶；而 <tt class="docutils literal"><span class="pre">MAKE_FUNCTION</span> <span class="pre">2</span></tt> 则表示栈顶code-obj对应的
function有两个默认参数.</p>
<p>前面 <tt class="docutils literal"><span class="pre">test.pyc</span></tt> 之外的东西, 比如 class/closure 的创建, 也都逃不过这
些指令, 具体每个指令的解释和用法可以参看 :
<a class="reference external" href="http://docs.python.org/release/2.7/library/dis.html#python-bytecode-instructions">http://docs.python.org/release/2.7/library/dis.html#python-bytecode-instructions</a></p>
</div>

<h2>Page(Article) Information / 页面(文章)信息:
  <a class="headerlink" href="#page-article-information" title="Permalink to this headline"></a>
</h2>
<ul class="simple">
  <li>Author : KDr2</li>
  <li>License : |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.en">
       Creative Commons BY-NC-ND 3.0
    </a> |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">
       CC3.0 : 自由转载-非商用-非衍生-保持署名
    </a> |
  </li>
  <li>Hosted on <a class="reference external" href="http://www.dreamhost.com/">DreamHost</a></li>
</ul>

</div>]]>
      </description>
      <content:encoded>
        <![CDATA[<div class="section" id="pyc">
<h1></h1>
<div class="section" id="id2">
<h2>PYC文件简介<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<p>不说废话,这里说的pyc文件就是 <a class="reference external" href="http://www.python.org">Python</a> 程序编译后得到的字节码文件
(py-&gt;pyc).</p>
</div>
<div class="section" id="id3">
<h2>基本格式<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h2>
<p>pyc文件一般由3个部分组成:</p>
<ul class="simple">
<li>最开始4个字节是一个Maigc int, 标识此pyc的版本信息, 不同的版本的 Magic
都在 <tt class="docutils literal"><span class="pre">Python/import.c</span></tt> 内定义</li>
<li>接下来四个字节还是个int,是pyc产生的时间(1970.01.01到产生pyc时候的秒
数)</li>
<li>接下来是个序列化了的 PyCodeObject(此结构在 <tt class="docutils literal"><span class="pre">Include/code.h</span></tt> 内定
义),序列化方法在 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内定义</li>
</ul>
<p>前两个字段的读写很简单,接下来咱们主要看一下 PyCodeObject 的序列化过程,
由于 PyCodeObject 内还有其他很多类型的 PyObject, 所以咱们从一般的
PyObject 的序列化开始看起:</p>
</div>
<div class="section" id="pyobject">
<h2>PyObject的序列化<a class="headerlink" href="#pyobject" title="Permalink to this headline">¶</a></h2>
<p>PyObject的序列化在 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内实现, 一般是先写入一个 byte
来标识此 PyObject 的类型, 每种 PyObject 对应的类型也在
<tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内定义:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//Python/marshal.c:22</span>
<span class="cp">#define TYPE_NULL               &#39;0&#39;</span>
<span class="cp">#define TYPE_NONE               &#39;N&#39;</span>
<span class="cp">#define TYPE_FALSE              &#39;F&#39;</span>
<span class="cp">#define TYPE_TRUE               &#39;T&#39;</span>
<span class="cp">#define TYPE_STOPITER           &#39;S&#39;</span>
<span class="cp">#define TYPE_ELLIPSIS           &#39;.&#39;</span>
<span class="cp">#define TYPE_INT                &#39;i&#39;</span>
<span class="cp">#define TYPE_INT64              &#39;I&#39;</span>
<span class="cp">#define TYPE_FLOAT              &#39;f&#39;</span>
<span class="cp">#define TYPE_BINARY_FLOAT       &#39;g&#39;</span>
<span class="cp">#define TYPE_COMPLEX            &#39;x&#39;</span>
<span class="cp">#define TYPE_BINARY_COMPLEX     &#39;y&#39;</span>
<span class="cp">#define TYPE_LONG               &#39;l&#39;</span>
<span class="cp">#define TYPE_STRING             &#39;s&#39;</span>
<span class="cp">#define TYPE_INTERNED           &#39;t&#39;</span>
<span class="cp">#define TYPE_STRINGREF          &#39;R&#39;</span>
<span class="cp">#define TYPE_TUPLE              &#39;(&#39;</span>
<span class="cp">#define TYPE_LIST               &#39;[&#39;</span>
<span class="cp">#define TYPE_DICT               &#39;{&#39;</span>
<span class="cp">#define TYPE_CODE               &#39;c&#39;</span>
<span class="cp">#define TYPE_UNICODE            &#39;u&#39;</span>
<span class="cp">#define TYPE_UNKNOWN            &#39;?&#39;</span>
<span class="cp">#define TYPE_SET                &#39;&lt;&#39;</span>
<span class="cp">#define TYPE_FROZENSET          &#39;&gt;&#39;</span>
</pre></div>
</div>
<p>之后是 PyObject 的具体数据内容, 变长的对象(str, tuple, list 等)往往还
包含了一个 4 bytes 的 len, 比如 PyIntObject 的存储可能是这样的:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>&#8216;i&#8217;</td>
<td>4 bytes int</td>
</tr>
<tr class="row-even"><td>&#8216;I&#8217;</td>
<td>8 bytes int</td>
</tr>
</tbody>
</table>
<p>而 PyStringObject 的存储是这样的:</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>&#8216;s&#8217;</td>
<td>4 bytes length</td>
<td>length bytes content(char[])</td>
</tr>
</tbody>
</table>
<p>PyTupleObject 和 PyListObject 的存储分别是:</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>&#8216;(&#8216;</td>
<td>4 bytes length</td>
<td>length 个 PyObject</td>
</tr>
<tr class="row-even"><td>&#8216;[&#8216;</td>
<td>4 bytes length</td>
<td>length 个 PyObject</td>
</tr>
</tbody>
</table>
<p>各种 PyObject 如何序列化,哪些内容被参与了序列化, 可以参看
<tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内的函数 <tt class="docutils literal"><span class="pre">w_object</span></tt> 函数, 接下来咱们着重看下前
面提到的 PyCodeObject 的序列化:</p>
</div>
<div class="section" id="pycodeobject">
<h2>PyCodeObject 的序列化<a class="headerlink" href="#pycodeobject" title="Permalink to this headline">¶</a></h2>
<p>结构体 PyCodeObject 在 <tt class="docutils literal"><span class="pre">Include/code.h</span></tt> 中定义如下:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//Include/code.h</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">PyObject_HEAD</span>
    <span class="kt">int</span> <span class="n">co_argcount</span><span class="p">;</span>        <span class="cm">/* #arguments, except *args */</span>
    <span class="kt">int</span> <span class="n">co_nlocals</span><span class="p">;</span>     <span class="cm">/* #local variables */</span>
    <span class="kt">int</span> <span class="n">co_stacksize</span><span class="p">;</span>       <span class="cm">/* #entries needed for evaluation stack */</span>
    <span class="kt">int</span> <span class="n">co_flags</span><span class="p">;</span>       <span class="cm">/* CO_..., see below */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_code</span><span class="p">;</span>      <span class="cm">/* instruction opcodes */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_consts</span><span class="p">;</span>    <span class="cm">/* list (constants used) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_names</span><span class="p">;</span>     <span class="cm">/* list of strings (names used) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_varnames</span><span class="p">;</span>  <span class="cm">/* tuple of strings (local variable names) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_freevars</span><span class="p">;</span>  <span class="cm">/* tuple of strings (free variable names) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_cellvars</span><span class="p">;</span>      <span class="cm">/* tuple of strings (cell variable names) */</span>
    <span class="cm">/* The rest doesn&#39;t count for hash/cmp */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_filename</span><span class="p">;</span>  <span class="cm">/* string (where it was loaded from) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_name</span><span class="p">;</span>      <span class="cm">/* string (name, for reference) */</span>
    <span class="kt">int</span> <span class="n">co_firstlineno</span><span class="p">;</span>     <span class="cm">/* first source line number */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_lnotab</span><span class="p">;</span>    <span class="cm">/* string (encoding addr&lt;-&gt;lineno mapping) See</span>
<span class="cm">                   Objects/lnotab_notes.txt for details. */</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">co_zombieframe</span><span class="p">;</span>     <span class="cm">/* for optimization only (see frameobject.c) */</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">co_weakreflist</span><span class="p">;</span>   <span class="cm">/* to support weakrefs to code objects */</span>
<span class="p">}</span> <span class="n">PyCodeObject</span><span class="p">;</span>
</pre></div>
</div>
<p>我们再看 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 里面的 <tt class="docutils literal"><span class="pre">w_object</span></tt> 函数,从中找出写
PyCodeObject 的部分如下:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//...</span>
<span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">PyCode_Check</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">PyCodeObject</span> <span class="o">*</span><span class="n">co</span> <span class="o">=</span> <span class="p">(</span><span class="n">PyCodeObject</span> <span class="o">*</span><span class="p">)</span><span class="n">v</span><span class="p">;</span>
    <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_CODE</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_argcount</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_nlocals</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_stacksize</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_flags</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_code</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_consts</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_names</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_varnames</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_freevars</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_cellvars</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_filename</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_name</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_long</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_firstlineno</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_object</span><span class="p">(</span><span class="n">co</span><span class="o">-&gt;</span><span class="n">co_lnotab</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//...</span>
</pre></div>
</div>
<p>根据上面两段代码,我们很容易就能看到 PyCodeObject 里哪些字段需要参数序
列化了,我们就挨个解释下需要序列化的字段们:</p>
<ul class="simple">
<li>co_argcount : code需要的位置参数个数,不包括变长参数(*args和**kwargs)</li>
<li>co_nlocals : code内所有的局部变量的个数,包括所有参数</li>
<li>co_stacksize : code段运行时所需要的最大栈深度</li>
<li>co_flags : 一些标识位,也在code.h里定义,注释很清楚,比如
CO_NOFREE(64) 表示此 PyCodeObject 内无 freevars 和 cellvars 等</li>
<li>co_code : PyStringObject(&#8216;s&#8217;), code对应的字节码(参看
<tt class="docutils literal"><span class="pre">Include/opcode.h</span></tt> 以及此文后续章节)</li>
<li>co_consts : 所有常量组成的tuple</li>
<li>co_names : code所用的到符号表, tuple类型,元素是字符串</li>
<li>co_varnames : code所用到的局部变量名, tuple类型, 元素是
PyStringObject(&#8216;s/t/R&#8217;)</li>
<li>co_freevars : code所用到的freevar的变量名,tuple类型, 元素是
PyStringObject(&#8216;s/t/R&#8217;)</li>
<li>co_cellvars : code所用到的cellvar的变量名,tuple类型, 元素是
PyStringObject(&#8216;s/t/R&#8217;)</li>
<li>co_filename : PyStringObject(&#8216;s&#8217;), 此code对应的py文件</li>
<li>co_name : 此code的名称</li>
<li>co_firstlineno : 此code对应的py文件里的第一行的行号</li>
<li>co_lnotab : PyStringObject(&#8216;s&#8217;),指令与行号的对应表</li>
</ul>
<p>在 Python 代码中,每个作用域(<em>或者叫block或者名字空间?</em>)对应一个
PyCodeObject 对象, 所以会出现嵌套: 比如 一个 module 类 定义了 N 个
class, 每个 class 内又定义了 M 个方法. 每个 <strong>子作用域</strong> 对应的
PyCodeObject 会出现在它的 <strong>父作用域</strong> 对应的 PyCodeObject 的
co_consts 字段里.</p>
<p>接下来用个例子对上面的某些字段做个说明, 比如下面的python代码</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#test.py</span>
<span class="kn">import</span> <span class="nn">struct</span>

<span class="k">def</span> <span class="nf">abc</span><span class="p">(</span><span class="n">c</span><span class="p">):</span>
    <span class="n">a</span><span class="o">=</span><span class="mi">1</span>
    <span class="n">b</span><span class="o">=</span><span class="mi">2</span>
    <span class="k">return</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s">&quot;S&quot;</span><span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="o">+</span><span class="n">c</span><span class="p">)</span>

<span class="n">var_a</span><span class="o">=</span><span class="s">&quot;abc&quot;</span>
<span class="n">var_b</span><span class="o">=</span><span class="p">{</span><span class="n">var_a</span><span class="p">:</span><span class="mi">123</span><span class="p">,</span><span class="s">&quot;sec_key&quot;</span><span class="p">:</span><span class="n">abc</span><span class="p">}</span>
</pre></div>
</div>
<p>它编译后对应的 pyc 在 <tt class="docutils literal"><span class="pre">magic</span></tt> 和 <tt class="docutils literal"><span class="pre">time</span></tt> 后就放着一个 PyCodeObject
对象, 这个对象的个字段指如下</p>
<table border="1" class="docutils">
<caption><strong>test.py对应PyCodeObject中各字段的值</strong></caption>
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">字段</th>
<th class="head">值</th>
<th class="head">注释</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>co_argcount</td>
<td>0</td>
<td>模块没有参数</td>
</tr>
<tr class="row-odd"><td>co_nlocals</td>
<td>0</td>
<td>模块没有局部变量</td>
</tr>
<tr class="row-even"><td>co_stacksize</td>
<td>3</td>
<td>栈最大尺寸</td>
</tr>
<tr class="row-odd"><td>co_flags</td>
<td>64</td>
<td>CO_NOFREE</td>
</tr>
<tr class="row-even"><td>co_code</td>
<td>&#8216;dx00x00d...&#8217;</td>
<td>字节码序列</td>
</tr>
<tr class="row-odd"><td>co_consts</td>
<td>(-1, None, another-code-obj...)</td>
<td>所有常量,包括模块里的
function,method</td>
</tr>
<tr class="row-even"><td>co_names</td>
<td>(&#8216;struct&#8217;, &#8216;abc&#8217;, &#8216;var_a&#8217;, &#8216;var_b&#8217;)</td>
<td>此作用域内用到的所
有符号</td>
</tr>
<tr class="row-odd"><td>co_varnames</td>
<td>()</td>
<td>局部变量名(模块没有局部变量)</td>
</tr>
<tr class="row-even"><td>co_freevars</td>
<td>()</td>
<td>freevars</td>
</tr>
<tr class="row-odd"><td>co_cellvars</td>
<td>()</td>
<td>cellvars</td>
</tr>
<tr class="row-even"><td>co_filename</td>
<td>test.py</td>
<td>源码文件名</td>
</tr>
<tr class="row-odd"><td>co_name</td>
<td>&#8216;&lt;module&gt;&#8217;</td>
<td>code名字,模块名都是&lt;module&gt;,class是类名,func是
函数名</td>
</tr>
<tr class="row-even"><td>co_firstlineno</td>
<td>3</td>
<td>此code对应作用域的第一行的行号</td>
</tr>
<tr class="row-odd"><td>co_lnotab</td>
<td>&#8216;x0cx02tx05x06x01&#8217;</td>
<td>行号表</td>
</tr>
</tbody>
</table>
<p>这其中的 <strong>co_consts</strong> 里面的第三个元素是function abc的PyCodeObject,
我们来看下function abc的code的各字段:</p>
<table border="1" class="docutils">
<caption><strong>function abc 对应PyCodeObject中各字段的值</strong></caption>
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">字段</th>
<th class="head">值</th>
<th class="head">注释</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>co_argcount</td>
<td>1</td>
<td>1个参数c</td>
</tr>
<tr class="row-odd"><td>co_nlocals</td>
<td>3</td>
<td>1个参数c, 两个局部变量a,b</td>
</tr>
<tr class="row-even"><td>co_stacksize</td>
<td>4</td>
<td>栈最大尺寸</td>
</tr>
<tr class="row-odd"><td>co_flags</td>
<td>67</td>
<td>CO_OPTIMIZATION | CO_NEWLOCALS | CO_NOFREE</td>
</tr>
<tr class="row-even"><td>co_code</td>
<td>&#8216;dx01x00}...&#8217;</td>
<td>字节码序列</td>
</tr>
<tr class="row-odd"><td>co_consts</td>
<td>(None, 1, 2, &#8216;S&#8217;)</td>
<td>函数里用到的所有常量</td>
</tr>
<tr class="row-even"><td>co_names</td>
<td>(&#8216;struct&#8217;, &#8216;pack&#8217;)</td>
<td>此作用域内用到的所有符号</td>
</tr>
<tr class="row-odd"><td>co_varnames</td>
<td>(&#8216;c&#8217;, &#8216;a&#8217;, &#8216;b&#8217;)</td>
<td>局部变量名</td>
</tr>
<tr class="row-even"><td>co_freevars</td>
<td>()</td>
<td>freevars</td>
</tr>
<tr class="row-odd"><td>co_cellvars</td>
<td>()</td>
<td>cellvars</td>
</tr>
<tr class="row-even"><td>co_filename</td>
<td>test.py</td>
<td>源码文件名</td>
</tr>
<tr class="row-odd"><td>co_name</td>
<td>&#8216;abc&#8217;</td>
<td>code名字,func是函数名</td>
</tr>
<tr class="row-even"><td>co_firstlineno</td>
<td>5</td>
<td>此code对应作用域的第一行的行号</td>
</tr>
<tr class="row-odd"><td>co_lnotab</td>
<td>&#8216;x00x01x06x01x06x01&#8217;</td>
<td>行号表</td>
</tr>
</tbody>
</table>
<div class="section" id="test-py-test-pyc">
<h3>图解 test.py 与 test.pyc 的结构关系<a class="headerlink" href="#test-py-test-pyc" title="Permalink to this headline">¶</a></h3>
<br /><br /><img alt="../_images/pyc_format_example_0.png" src="../_images/pyc_format_example_0.png" style="width: 800px; height: 1057px;" />
</div>
<div class="section" id="co-freevars-co-cellvars">
<h3>co_freevars 与 co_cellvars<a class="headerlink" href="#co-freevars-co-cellvars" title="Permalink to this headline">¶</a></h3>
<p>这两个字段是给 Closure 准备的(<em>Python里没有真正的Closure</em>),通俗的说就
是函数嵌套的时候用的到,比如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">outter</span><span class="p">(</span><span class="n">o1</span><span class="p">,</span><span class="n">o2</span><span class="p">):</span>
    <span class="n">fc1</span><span class="o">=</span><span class="n">o1</span><span class="o">+</span><span class="n">o2</span>
    <span class="n">fc2</span><span class="o">=</span><span class="n">o1</span><span class="o">*</span><span class="n">o2</span>
    <span class="k">def</span> <span class="nf">inner</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
        <span class="k">return</span> <span class="p">(</span><span class="n">fc1</span><span class="o">+</span><span class="n">fc2</span><span class="p">)</span><span class="o">*</span><span class="n">i</span>
</pre></div>
</div>
<ul class="simple">
<li>对于 outter 函数来说,他的局部变量 fc1 和 fc2 被它内部嵌套的函数所引
用,则 fc1 和 fc2 变成它的 <strong>cellvars</strong> 而不是局部变量 varnames</li>
<li>对于 inner 函数, fc1 和 fc2 既不是局部变量也不是全局变量,他引用自外
层函数, 则 fc1 和 fc2 是 inner 的 <strong>freevars</strong></li>
</ul>
</div>
<div class="section" id="pystringobject">
<h3>PyStringObject 的序列化<a class="headerlink" href="#pystringobject" title="Permalink to this headline">¶</a></h3>
<p>通过前面的介绍,你可能会发现PyCodeObject里面的用到str(&#8216;s&#8217;)类型的地方很
多,什么co_consts啊,co_names,co_varnames,co_freevars,co_cellvars等等都
是str的tuple,里面的str重复的也比较多,要是一股脑这么写进去可能会占用很
大空间,于是w_object里对PyStringObject的序列化又多加了两种类型:</p>
<ul class="simple">
<li>&#8216;t&#8217; : interned-string, 暂时可能简单理解为 pyc 里回重复出现的 str, 这
个类型就是简单的把 str 的类型 &#8216;s&#8217; 改成 &#8216;t&#8217; 了,后面还是跟
length(4bytes) 和 content(char[])</li>
<li>&#8216;R&#8217; : 指向 interned-string 的字符串引用, &#8216;R&#8217;后面跟4个 bytea 的引用序
号</li>
</ul>
<p>具体看 <tt class="docutils literal"><span class="pre">Python/marshal.c</span></tt> 内 <tt class="docutils literal"><span class="pre">w_object</span></tt> 的相关实现:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="c1">//...</span>
<span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">PyString_CheckExact</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span> <span class="o">&amp;&amp;</span> <span class="n">PyString_CHECK_INTERNED</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">PyObject</span> <span class="o">*</span><span class="n">o</span> <span class="o">=</span> <span class="n">PyDict_GetItem</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span><span class="p">,</span> <span class="n">v</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">o</span><span class="p">)</span> <span class="p">{</span>
            <span class="kt">long</span> <span class="n">w</span> <span class="o">=</span> <span class="n">PyInt_AsLong</span><span class="p">(</span><span class="n">o</span><span class="p">);</span>
            <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_STRINGREF</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
            <span class="n">w_long</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
            <span class="k">goto</span> <span class="n">exit</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span> <span class="p">{</span>
            <span class="kt">int</span> <span class="n">ok</span><span class="p">;</span>
            <span class="n">o</span> <span class="o">=</span> <span class="n">PyInt_FromSsize_t</span><span class="p">(</span><span class="n">PyDict_Size</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span><span class="p">));</span>
            <span class="n">ok</span> <span class="o">=</span> <span class="n">o</span> <span class="o">&amp;&amp;</span>
                 <span class="n">PyDict_SetItem</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">strings</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">o</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="n">Py_XDECREF</span><span class="p">(</span><span class="n">o</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ok</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">p</span><span class="o">-&gt;</span><span class="n">depth</span><span class="o">--</span><span class="p">;</span>
                <span class="n">p</span><span class="o">-&gt;</span><span class="n">error</span> <span class="o">=</span> <span class="n">WFERR_UNMARSHALLABLE</span><span class="p">;</span>
                <span class="k">return</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_INTERNED</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="n">w_byte</span><span class="p">(</span><span class="n">TYPE_STRING</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">n</span> <span class="o">=</span> <span class="n">PyString_GET_SIZE</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="n">INT_MAX</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/* huge strings are not supported */</span>
        <span class="n">p</span><span class="o">-&gt;</span><span class="n">depth</span><span class="o">--</span><span class="p">;</span>
        <span class="n">p</span><span class="o">-&gt;</span><span class="n">error</span> <span class="o">=</span> <span class="n">WFERR_UNMARSHALLABLE</span><span class="p">;</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">w_long</span><span class="p">((</span><span class="kt">long</span><span class="p">)</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
    <span class="n">w_string</span><span class="p">(</span><span class="n">PyString_AS_STRING</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//...</span>
</pre></div>
</div>
</div>
<div class="section" id="id4">
<h3>行号对照表<a class="headerlink" href="#id4" title="Permalink to this headline">¶</a></h3>
<p>co_lnotab可以看做是(字节码在co_opcode中的index增量(1 byte),对应的源码
的行号增量(1-bytes))顺次串成的的字节数组(字符串).</p>
</div>
</div>
<div class="section" id="co-code-pythonopcode">
<h2>字段 co_code 与 Python的OPCODE<a class="headerlink" href="#co-code-pythonopcode" title="Permalink to this headline">¶</a></h2>
<p>PyCodeObject 的 co_code 字段就是 python opcode 组成的序列, 具体有哪些
opcode可以参看 <tt class="docutils literal"><span class="pre">Include/opcode.h</span></tt> , 这里面有些opcode有参数,有些没有
参数, 从opcode.h内的代码段:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="cp">#define HAVE_ARGUMENT 90  </span><span class="cm">/* Opcodes from here have an argument: */</span><span class="cp"></span>
<span class="c1">//...</span>
<span class="cp">#define HAS_ARG(op) ((op) &gt;= HAVE_ARGUMENT)</span>
</pre></div>
</div>
<p>可以看出,大于等与90的opcode是有参数的, 有参数的opcode的参数是两个
unsigned byte, 第一个是操作数, 第二个目前固定为0x00但是不能省略,举例来
说,我要把当前code的co_consts里的第二个常量(index是1)载入到栈顶,则对应
的opcode序列为: <tt class="docutils literal"><span class="pre">|LOAD_CONST|0x01|0x00|</span></tt> ,也就是 <tt class="docutils literal"><span class="pre">'0x640x010x00'</span></tt></p>
<p>其他的opcode大都类似,主要是对函数调用栈以及co_consts, co_varnames,
co_freevars, co_cellvars的操作, 还有些BUILD_CLASS, BUILD_MAP,
BUILD_LIST, BUILD_TUPLE, BUILD_SLICE, MAKE_FUNCTION, MAKE_CLOSURE 等构
建对象的特殊指令.</p>
<p>有参数的 opcode 的参数的参数大多时候是个 index, 比如 <tt class="docutils literal"><span class="pre">LOAD_CONST</span> <span class="pre">1</span></tt>
的 1 就是个 index, 表示把当前 <tt class="docutils literal"><span class="pre">PyCodeObject.co_consts[1]</span></tt> 这个常量载
入到栈顶, <tt class="docutils literal"><span class="pre">LOAD_FAST</span> <span class="pre">2</span></tt> 则是把 <tt class="docutils literal"><span class="pre">PyCodeObject.co_varnames[2]</span></tt> 这个
局部变量载入到栈顶；而 <tt class="docutils literal"><span class="pre">MAKE_FUNCTION</span> <span class="pre">2</span></tt> 则表示栈顶code-obj对应的
function有两个默认参数.</p>
<p>前面 <tt class="docutils literal"><span class="pre">test.pyc</span></tt> 之外的东西, 比如 class/closure 的创建, 也都逃不过这
些指令, 具体每个指令的解释和用法可以参看 :
<a class="reference external" href="http://docs.python.org/release/2.7/library/dis.html#python-bytecode-instructions">http://docs.python.org/release/2.7/library/dis.html#python-bytecode-instructions</a></p>
</div>

<h2>Page(Article) Information / 页面(文章)信息:
  <a class="headerlink" href="#page-article-information" title="Permalink to this headline"></a>
</h2>
<ul class="simple">
  <li>Author : KDr2</li>
  <li>License : |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.en">
       Creative Commons BY-NC-ND 3.0
    </a> |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">
       CC3.0 : 自由转载-非商用-非衍生-保持署名
    </a> |
  </li>
  <li>Hosted on <a class="reference external" href="http://www.dreamhost.com/">DreamHost</a></li>
</ul>

</div>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


    <item>
      <title><![CDATA[Back to Dreamhost [20101128] &mdash; KDr2&#39;s Personal Website]]></title>

      <link>http://kdr2.net/blog/20101128_back_to_dreamhost.html</link>
      <!-- comments>http://link#comments</comments -->
      <pubDate>Sun, 28 Nov 2010 10:17:00 +0800</pubDate>
      <dc:creator>KDr2</dc:creator>

      <category><![CDATA[article]]></category>

      <guid isPermaLink="false">http://kdr2.net/blog/20101128_back_to_dreamhost.html</guid>
      <description>
        <![CDATA[<div class="section" id="back-to-dreamhost-20101128">
<h1></h1>
<div class="section" id="id2">
<h2>讨厌在线写东西<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<p>用过 <a class="reference external" href="http://www.wordpress.org">WordPress</a>, 用过Drupal, 用过门户们运营的Blog, 都要在线写东西，这
是我所不能接受的，找过一些离线书写的工具，体验也都很差，俺要找个离线写
的，最好能在俺的 <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a> 里写的(blogger.el等体验也很差...)，没找到趁手
的，干脆自己攒吧，于是现在的站点就来了，用 <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a> 写 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, 提交到
<a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a>, 服务器上用crontab定时pull <a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a> 上的 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, 之后
再用 <a class="reference external" href="http://sphinx.pocoo.org/">SphinxDoc</a> 把 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 编译成html放到webserver的根目录下，就好了，一
个静态的站就攒起来了，每次更新就在 <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a> 里舒舒服服的编辑 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 之后
commit/push到 <a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a> 上就可以。这样不仅做到了离线写作，站点的
<a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 代码本地有， <a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a> 上有，server上也有，备份也不用额外做了。</p>
</div>
<div class="section" id="id3">
<h2>我要动态站<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h2>
<p>一个静态的站点，貌似没什么意思... 写的狗屁玩意连评论下都不行，我想要一
些动态功能和朋友交流， 该咋办呢...</p>
<p>还是得自己动手丰衣足食啊，先在某 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 文件里写个javascript脚本，操作
dom生成用于提交comment的表单，然后做个动态的(Rest风格?)的服务来接收
用户comment时候发起的请求，在前面提到js里加上页面加载时的从动态的(Rest
风格?)的服务那里获取与当前页面相关的comments，灌到页面里就好了。要做就
做，不到2个小时，做成了，现在想在某页面里开启评论功能只要include写有js
脚本的那个 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 文件即可。</p>
<p>顺带说一句，这个动态的评论最初我使用 <a class="reference external" href="http://www.djangoproject.com/">django</a> 做的，后来由于发现
<a class="reference external" href="http://www.pylonshq.com/">pylons</a> 更符合我的胃口，就换到 <a class="reference external" href="http://www.pylonshq.com/">pylons</a> 了。</p>
<p>其他还需要什么动态服务，基本就两个思路:</p>
<ul class="simple">
<li>看有现成的第三方的线上服务能直接用不，有的话直接拿来主义。</li>
<li>上一条中没有的话就自己整一个，按comment功能的方式加上。</li>
</ul>
</div>
<div class="section" id="back-to-dreamhost">
<h2>为什么说 &#8220;Back to Dreamhost&#8221;?<a class="headerlink" href="#back-to-dreamhost" title="Permalink to this headline">¶</a></h2>
<p>2007年就买了 <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 的虚拟主机，那时还用 <a class="reference external" href="http://www.wordpress.org">WordPress</a>, <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 上也没有
fastcgi支持，基本只能放php程序和静态的东西，后来因为一次服务器数据转移
停了下服务, <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 为了补偿就给升级成 <strong>存储不限，流量不限</strong> 的账号了，
但是我为了方便自己折腾，忘了去年还是今年初买了个低配的VPS, 在上面跑些
自己的程序以及做一些不能说太细的事情，前面的我所那些工作都是在我用那个
VPS的时候完成的，也是放到那VPS上的。</p>
<p>但是，这个周末，我把这些都搬回DreamHost上了。才发现现在 <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 的php都
是fastcgi方式在跑了(我土...), 静态页面的迁移体不用说了，在上面用
fastcgi跑 <a class="reference external" href="http://www.pylonshq.com/">pylons</a> 倒是折腾了一番，先是因为我的 &#8216;追新强迫症&#8217; 让我启用
<a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 自带的 Python 2.5.2 自己装了个 2.7, 之后开始测试fastcgi就开始不
断500了，log里也只说什么 header byte(0) 之类的， 后来在 fastcgi里打印
了下环境变量以及sys.path，发现少了一些egg路径(因为我在.bashrc自己加了
条 PYTHONPATH, easy_install装到这个PYTHONPATH里面了)，然后我有把fcgi改
成让cgi handler处理，发现error.log里有东西了，说paster.deploy找不到...
真相大白了...</p>
<p>说下整个步骤吧:</p>
<p><strong>安装Python</strong></p>
<p>我装到了$HOME/local下 (configure的时候指定&#8211;prefix=$HOME/local),之后
在.bashrc里写:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$HOME</span>/local/bin:<span class="nv">$HOME</span>/local/script:<span class="nv">$PATH</span>
<span class="nb">export </span><span class="nv">PYTHONPATH</span><span class="o">=</span><span class="nv">$HOME</span>/local/lib/python
<span class="nb">alias </span><span class="nv">python</span><span class="o">=</span><span class="nv">$HOME</span>/local/bin/python
</pre></div>
</div>
<p>之所以要 export PYTHONPATH=$HOME/local/lib/python 是因为那些python的本
地library(比如_socket.so)都装在了这里，而这个路径没在sys.path里。</p>
<p>之后安装easy_install(setuptools), 然后用easy_install安装pylons, flup,
sqlalchemy, mysql-python等包，按惯例这些包会被装到
$HOME/local/lib/python2.7/site-packages/下，但是由于前面我 export
PYTHONPATH=$HOME/local/lib/python, 导致这些包都装在了
$HOME/local/lib/python 下面，造成了fastcgi脚本里需要额外
的设置路径。 其实把$HOME/local/lib/python下面的eggs移到
$HOME/local/lib/python2.7/site-packages/下估计也可以。</p>
<p><strong>dispatch.fcgi</strong></p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!$HOME/local/bin/python</span>

<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">glob</span>
<span class="k">def</span> <span class="nf">add_path_and_eggs</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
    <span class="n">eggs</span><span class="o">=</span><span class="n">glob</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="n">path</span><span class="o">+</span><span class="s">&quot;/*.egg&quot;</span><span class="p">)</span>
    <span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">eggs</span><span class="p">]</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">path</span><span class="p">)</span>

<span class="n">add_path_and_eggs</span><span class="p">(</span><span class="s">&quot;$HOME/local/lib/python&quot;</span><span class="p">)</span>
<span class="n">add_path_and_eggs</span><span class="p">(</span><span class="s">&#39;$HOME/local/lib/python2.7/site-packages&#39;</span><span class="p">)</span>
<span class="n">other_path</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python27.zip&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/plat-linux2&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/lib-tk&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/lib-old&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/lib-dynload&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">other_path</span><span class="p">]</span>

<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">from</span> <span class="nn">paste.deploy</span> <span class="kn">import</span> <span class="n">loadapp</span>

<span class="n">config_file</span> <span class="o">=</span> <span class="s">&quot;$HOME/xxx/pylon-app/production.ini&quot;</span>
<span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">loadapp</span><span class="p">(</span><span class="s">&#39;config:&#39;</span><span class="o">+</span><span class="n">config_file</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">serve_with_flup</span><span class="p">():</span>
    <span class="kn">from</span> <span class="nn">flup.server.fcgi</span> <span class="kn">import</span> <span class="n">WSGIServer</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">fileConfig</span><span class="p">(</span><span class="n">config_file</span><span class="p">)</span>
    <span class="n">WSGIServer</span><span class="p">(</span><span class="n">wsgi_app</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>

<span class="n">serve_with_flup</span><span class="p">()</span>
</pre></div>
</div>
<p><strong>.htaccess</strong></p>
<div class="highlight-bash"><div class="highlight"><pre><span class="c">#AddHandler cgi-script .cgi</span>
AddHandler fastcgi-script .fcgi
Options +FollowSymLinks +ExecCGI

RewriteEngine On
RewriteRule ^dispatch<span class="se">\.</span>fcgi/ - <span class="o">[</span>L<span class="o">]</span>
RewriteRule ^<span class="o">(</span>.*<span class="o">)</span><span class="nv">$ </span>dispatch.fcgi <span class="o">[</span>L<span class="o">]</span>
</pre></div>
</div>
<p><strong>经验，提示</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 上fcgi出错时不好找原因，可以把fcgi当cgi跑来看看错误信息</li>
</ul>
</div>

<h2>Page(Article) Information / 页面(文章)信息:
  <a class="headerlink" href="#page-article-information" title="Permalink to this headline"></a>
</h2>
<ul class="simple">
  <li>Author : KDr2</li>
  <li>License : |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.en">
       Creative Commons BY-NC-ND 3.0
    </a> |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">
       CC3.0 : 自由转载-非商用-非衍生-保持署名
    </a> |
  </li>
  <li>Hosted on <a class="reference external" href="http://www.dreamhost.com/">DreamHost</a></li>
</ul>

</div>]]>
      </description>
      <content:encoded>
        <![CDATA[<div class="section" id="back-to-dreamhost-20101128">
<h1></h1>
<div class="section" id="id2">
<h2>讨厌在线写东西<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<p>用过 <a class="reference external" href="http://www.wordpress.org">WordPress</a>, 用过Drupal, 用过门户们运营的Blog, 都要在线写东西，这
是我所不能接受的，找过一些离线书写的工具，体验也都很差，俺要找个离线写
的，最好能在俺的 <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a> 里写的(blogger.el等体验也很差...)，没找到趁手
的，干脆自己攒吧，于是现在的站点就来了，用 <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a> 写 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, 提交到
<a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a>, 服务器上用crontab定时pull <a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a> 上的 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, 之后
再用 <a class="reference external" href="http://sphinx.pocoo.org/">SphinxDoc</a> 把 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 编译成html放到webserver的根目录下，就好了，一
个静态的站就攒起来了，每次更新就在 <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a> 里舒舒服服的编辑 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 之后
commit/push到 <a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a> 上就可以。这样不仅做到了离线写作，站点的
<a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 代码本地有， <a class="reference external" href="http://github.com/KDr2/kdr2.net">GitHub</a> 上有，server上也有，备份也不用额外做了。</p>
</div>
<div class="section" id="id3">
<h2>我要动态站<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h2>
<p>一个静态的站点，貌似没什么意思... 写的狗屁玩意连评论下都不行，我想要一
些动态功能和朋友交流， 该咋办呢...</p>
<p>还是得自己动手丰衣足食啊，先在某 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 文件里写个javascript脚本，操作
dom生成用于提交comment的表单，然后做个动态的(Rest风格?)的服务来接收
用户comment时候发起的请求，在前面提到js里加上页面加载时的从动态的(Rest
风格?)的服务那里获取与当前页面相关的comments，灌到页面里就好了。要做就
做，不到2个小时，做成了，现在想在某页面里开启评论功能只要include写有js
脚本的那个 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> 文件即可。</p>
<p>顺带说一句，这个动态的评论最初我使用 <a class="reference external" href="http://www.djangoproject.com/">django</a> 做的，后来由于发现
<a class="reference external" href="http://www.pylonshq.com/">pylons</a> 更符合我的胃口，就换到 <a class="reference external" href="http://www.pylonshq.com/">pylons</a> 了。</p>
<p>其他还需要什么动态服务，基本就两个思路:</p>
<ul class="simple">
<li>看有现成的第三方的线上服务能直接用不，有的话直接拿来主义。</li>
<li>上一条中没有的话就自己整一个，按comment功能的方式加上。</li>
</ul>
</div>
<div class="section" id="back-to-dreamhost">
<h2>为什么说 &#8220;Back to Dreamhost&#8221;?<a class="headerlink" href="#back-to-dreamhost" title="Permalink to this headline">¶</a></h2>
<p>2007年就买了 <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 的虚拟主机，那时还用 <a class="reference external" href="http://www.wordpress.org">WordPress</a>, <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 上也没有
fastcgi支持，基本只能放php程序和静态的东西，后来因为一次服务器数据转移
停了下服务, <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 为了补偿就给升级成 <strong>存储不限，流量不限</strong> 的账号了，
但是我为了方便自己折腾，忘了去年还是今年初买了个低配的VPS, 在上面跑些
自己的程序以及做一些不能说太细的事情，前面的我所那些工作都是在我用那个
VPS的时候完成的，也是放到那VPS上的。</p>
<p>但是，这个周末，我把这些都搬回DreamHost上了。才发现现在 <a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 的php都
是fastcgi方式在跑了(我土...), 静态页面的迁移体不用说了，在上面用
fastcgi跑 <a class="reference external" href="http://www.pylonshq.com/">pylons</a> 倒是折腾了一番，先是因为我的 &#8216;追新强迫症&#8217; 让我启用
<a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 自带的 Python 2.5.2 自己装了个 2.7, 之后开始测试fastcgi就开始不
断500了，log里也只说什么 header byte(0) 之类的， 后来在 fastcgi里打印
了下环境变量以及sys.path，发现少了一些egg路径(因为我在.bashrc自己加了
条 PYTHONPATH, easy_install装到这个PYTHONPATH里面了)，然后我有把fcgi改
成让cgi handler处理，发现error.log里有东西了，说paster.deploy找不到...
真相大白了...</p>
<p>说下整个步骤吧:</p>
<p><strong>安装Python</strong></p>
<p>我装到了$HOME/local下 (configure的时候指定&#8211;prefix=$HOME/local),之后
在.bashrc里写:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$HOME</span>/local/bin:<span class="nv">$HOME</span>/local/script:<span class="nv">$PATH</span>
<span class="nb">export </span><span class="nv">PYTHONPATH</span><span class="o">=</span><span class="nv">$HOME</span>/local/lib/python
<span class="nb">alias </span><span class="nv">python</span><span class="o">=</span><span class="nv">$HOME</span>/local/bin/python
</pre></div>
</div>
<p>之所以要 export PYTHONPATH=$HOME/local/lib/python 是因为那些python的本
地library(比如_socket.so)都装在了这里，而这个路径没在sys.path里。</p>
<p>之后安装easy_install(setuptools), 然后用easy_install安装pylons, flup,
sqlalchemy, mysql-python等包，按惯例这些包会被装到
$HOME/local/lib/python2.7/site-packages/下，但是由于前面我 export
PYTHONPATH=$HOME/local/lib/python, 导致这些包都装在了
$HOME/local/lib/python 下面，造成了fastcgi脚本里需要额外
的设置路径。 其实把$HOME/local/lib/python下面的eggs移到
$HOME/local/lib/python2.7/site-packages/下估计也可以。</p>
<p><strong>dispatch.fcgi</strong></p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!$HOME/local/bin/python</span>

<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">glob</span>
<span class="k">def</span> <span class="nf">add_path_and_eggs</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
    <span class="n">eggs</span><span class="o">=</span><span class="n">glob</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="n">path</span><span class="o">+</span><span class="s">&quot;/*.egg&quot;</span><span class="p">)</span>
    <span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">eggs</span><span class="p">]</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">path</span><span class="p">)</span>

<span class="n">add_path_and_eggs</span><span class="p">(</span><span class="s">&quot;$HOME/local/lib/python&quot;</span><span class="p">)</span>
<span class="n">add_path_and_eggs</span><span class="p">(</span><span class="s">&#39;$HOME/local/lib/python2.7/site-packages&#39;</span><span class="p">)</span>
<span class="n">other_path</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python27.zip&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/plat-linux2&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/lib-tk&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/lib-old&#39;</span><span class="p">,</span>
            <span class="s">&#39;$HOME/local/lib/python2.7/lib-dynload&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">other_path</span><span class="p">]</span>

<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">from</span> <span class="nn">paste.deploy</span> <span class="kn">import</span> <span class="n">loadapp</span>

<span class="n">config_file</span> <span class="o">=</span> <span class="s">&quot;$HOME/xxx/pylon-app/production.ini&quot;</span>
<span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">loadapp</span><span class="p">(</span><span class="s">&#39;config:&#39;</span><span class="o">+</span><span class="n">config_file</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">serve_with_flup</span><span class="p">():</span>
    <span class="kn">from</span> <span class="nn">flup.server.fcgi</span> <span class="kn">import</span> <span class="n">WSGIServer</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">fileConfig</span><span class="p">(</span><span class="n">config_file</span><span class="p">)</span>
    <span class="n">WSGIServer</span><span class="p">(</span><span class="n">wsgi_app</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>

<span class="n">serve_with_flup</span><span class="p">()</span>
</pre></div>
</div>
<p><strong>.htaccess</strong></p>
<div class="highlight-bash"><div class="highlight"><pre><span class="c">#AddHandler cgi-script .cgi</span>
AddHandler fastcgi-script .fcgi
Options +FollowSymLinks +ExecCGI

RewriteEngine On
RewriteRule ^dispatch<span class="se">\.</span>fcgi/ - <span class="o">[</span>L<span class="o">]</span>
RewriteRule ^<span class="o">(</span>.*<span class="o">)</span><span class="nv">$ </span>dispatch.fcgi <span class="o">[</span>L<span class="o">]</span>
</pre></div>
</div>
<p><strong>经验，提示</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://www.dreamhost.com">DreamHost</a> 上fcgi出错时不好找原因，可以把fcgi当cgi跑来看看错误信息</li>
</ul>
</div>

<h2>Page(Article) Information / 页面(文章)信息:
  <a class="headerlink" href="#page-article-information" title="Permalink to this headline"></a>
</h2>
<ul class="simple">
  <li>Author : KDr2</li>
  <li>License : |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.en">
       Creative Commons BY-NC-ND 3.0
    </a> |
    <a class="reference external" href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">
       CC3.0 : 自由转载-非商用-非衍生-保持署名
    </a> |
  </li>
  <li>Hosted on <a class="reference external" href="http://www.dreamhost.com/">DreamHost</a></li>
</ul>

</div>]]>
      </content:encoded>
      <!-- wfw:commentRss>none/feed/</wfw:commentRss -->
      <!-- slash:comments>0</slash:comments -->
    </item>


  </channel>
</rss>
