<?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>Shine.IT</title>
	<atom:link href="http://blog.shine-it.net/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.shine-it.net</link>
	<description>Open Source, Python, Open ERP</description>
	<lastBuildDate>Tue, 17 Jan 2012 09:02:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>ssh 超时断开的解决方法</title>
		<link>http://blog.shine-it.net/linux/keep-ssh-connection-alive</link>
		<comments>http://blog.shine-it.net/linux/keep-ssh-connection-alive#comments</comments>
		<pubDate>Tue, 17 Jan 2012 08:54:08 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[sshd]]></category>
		<category><![CDATA[sshd_config]]></category>
		<category><![CDATA[ssh_config]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/linux/keep-ssh-connection-alive</guid>
		<description><![CDATA[当用ssh连接*Nix服务器，几分钟没有操作，ssh连接就会被断开。如何才能保持ssh连接不被超时断开呢？有两种方法： 服务器端设置 打开文件 /etc/ssh/sshd_config 找到 ClientAliveInterval 选项， 如果没有的话，添加此选项。如下设置表示每360秒(6分钟)向客户端发送一个是否保持连接的查询信息（该选项默认为0，表示不发送查询信息） ClientAliveInterval 360 客户端设置 打开文件 /etc/ssh/ssh_config 找到 ServerAliveInterval 选项， 如果没有的话，添加此选项。如下设置表示每360秒(6分钟)向服务器端发送一个是否保持连接的查询信息（该选项默认为0，表示不发送查询信息） ServerAliveInterval 360 当你需要连接到多个ssh服务器时，可以使用 客户端设置 的方法，如果你是管理一个ssh服务器，希望所有的ssh客户端不被自动超时断开的话可以使用 服务器端设置 网络书签]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<p>当用ssh连接*Nix服务器，几分钟没有操作，ssh连接就会被断开。如何才能保持ssh连接不被超时断开呢？有两种方法：</p>
<div class="section" id="id1">
<h3>服务器端设置</h3>
<p>打开文件 <cite>/etc/ssh/sshd_config</cite> 找到 <cite>ClientAliveInterval</cite> 选项， 如果没有的话，添加此选项。如下设置表示每360秒(6分钟)向客户端发送一个是否保持连接的查询信息（该选项默认为0，表示不发送查询信息）</p>
<pre class="literal-block">
ClientAliveInterval 360
</pre>
</div>
<div class="section" id="id2">
<h3>客户端设置</h3>
<p>打开文件 <cite>/etc/ssh/ssh_config</cite> 找到 <cite>ServerAliveInterval</cite> 选项， 如果没有的话，添加此选项。如下设置表示每360秒(6分钟)向服务器端发送一个是否保持连接的查询信息（该选项默认为0，表示不发送查询信息）</p>
<pre class="literal-block">
ServerAliveInterval 360
</pre>
<p>当你需要连接到多个ssh服务器时，可以使用 <a class="reference internal" href="#id2">客户端设置</a> 的方法，如果你是管理一个ssh服务器，希望所有的ssh客户端不被自动超时断开的话可以使用 <a class="reference internal" href="#id1">服务器端设置</a></p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;submitHeadline=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;title=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;title=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;title=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;bm_description=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;T=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;title=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;title=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95+@+http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fkeep-ssh-connection-alive&amp;t=ssh+%E8%B6%85%E6%97%B6%E6%96%AD%E5%BC%80%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/linux/keep-ssh-connection-alive/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入了解 Generator</title>
		<link>http://blog.shine-it.net/python/dive-into-generator</link>
		<comments>http://blog.shine-it.net/python/dive-into-generator#comments</comments>
		<pubDate>Tue, 14 Jun 2011 09:50:32 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[generator]]></category>
		<category><![CDATA[iterator]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/python/iterator-%e5%92%8c-generator</guid>
		<description><![CDATA[原文作者:David Beazley 中文编译:Tony (digitalsatori) 第一部分：Iterators 和 Generators简介 Iteration 枚举 众所周知Python有一个“for”语句 你可以用它来在一组对象上做循环操作 &#62;&#62;&#62; for x in [1, 4, 5, 10]: ... print x, ... 1 4 5 10 &#62;&#62;&#62; 你不仅仅可以对list做循环枚举操作，还可以对很多不同类型的对象做相同的操作 对Dict的枚举 对字典进行循环枚举操作，会得到该字典的keys &#62;&#62;&#62; prices = { 'GOOG' : 490.10, ... 'AAPL' : 145.23, ... 'YHOO' : 21.71 } ... &#62;&#62;&#62; for key in prices: ... print [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">

<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">原文作者:</th><td class="field-body">David Beazley</td>
</tr>
<tr class="field"><th class="docinfo-name">中文编译:</th><td class="field-body">Tony (digitalsatori)</td>
</tr>
</tbody>
</table>
<!-- -*- mode: rst -*- -->
<div class="section" id="iterators-generators">
<h3>第一部分：Iterators 和 Generators简介</h3>
<div class="section" id="iteration">
<h4>Iteration 枚举</h4>
<ul class="simple">
<li>众所周知Python有一个“for”语句</li>
<li>你可以用它来在一组对象上做循环操作</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; for x in [1, 4, 5, 10]:
...     print x,
...
1 4 5 10
&gt;&gt;&gt;
</pre>
<ul class="simple">
<li>你不仅仅可以对list做循环枚举操作，还可以对很多不同类型的对象做相同的操作</li>
</ul>
</div>
<div class="section" id="dict">
<h4>对Dict的枚举</h4>
<ul class="simple">
<li>对字典进行循环枚举操作，会得到该字典的keys</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; prices = { 'GOOG' : 490.10,
...            'AAPL' : 145.23,
...            'YHOO' : 21.71 }
...
&gt;&gt;&gt; for key in prices:
...     print key
...
YHOO
GOOG
AAPL
&gt;&gt;&gt;
</pre>
</div>
<div class="section" id="string">
<h4>对String的枚举</h4>
<ul class="simple">
<li>对字符串进行循环枚举操作，会得到字符</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; s = &quot;Yow!&quot;
&gt;&gt;&gt; for c in s:
...     print c
...
Y
o
w
!
&gt;&gt;&gt;
</pre>
</div>
<div class="section" id="id1">
<h4>对文件的枚举</h4>
<ul class="simple">
<li>对文件进行循环枚举操作，会得到文本行</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; for line in open(&quot;real.txt&quot;):
...     print line,
...
    Real Programmers write in FORTRAN
Maybe they do now,
in this decadent era of
Lite beer, hand calculators, and &quot;user-friendly&quot; software
but back in the Good Old Days,
when the term &quot;software&quot; sounded funny
and Real Computers were made out of drums and vacuum tubesReal Programmers wrote in machine code.
Not FORTRAN. Not RATFOR. Not, even, assembly language.
Machine Code.
Raw, unadorned, inscrutable hexadecimal numbers.
Directly.
</pre>
</div>
<div class="section" id="consume">
<h4>“消费”(Consume) 可枚举对象</h4>
<ul>
<li><dl class="first docutils">
<dt>很多函数可以消费 <strong>可枚举</strong> 对象, 比如</dt>
<dd><ul class="first last">
<li><p class="first">消减（Reductions）：</p>
<p>sum(s), min(s), max(s)</p>
</li>
<li><p class="first">构造器(Constructors):</p>
<p>list(s), tuple(s), set(s), dict(s)</p>
</li>
<li><p class="first">in 操作符</p>
<p>item in s</p>
</li>
<li><p class="first">以及函数库中众多的其他函数</p>
</li>
</ul>
</dd>
</dl>
</li>
</ul>
</div>
<div class="section" id="iteration-protocol">
<h4>枚举协议（Iteration Protocol)</h4>
<ul class="simple">
<li>能对不同的对象进行枚举操作的原因是有一个特别的协议</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; items = [1, 4, 5]
&gt;&gt;&gt; it = iter(items)
&gt;&gt;&gt; it.next()
1
&gt;&gt;&gt; it.next()
4
&gt;&gt;&gt; it.next()
5
&gt;&gt;&gt; it.next()
Traceback (most recent call last):
    File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
StopIteration
&gt;&gt;&gt;
</pre>
<ul class="simple">
<li>深入了解for语句</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">for</span> x <span style="color: #AA22FF; font-weight: bold">in</span> obj:
  <span style="color: #408080; font-style: italic"># statements</span>
</pre></div>
</div><ul class="simple">
<li>其本质是</li>
</ul>
<div class="codeblock"><div class="highlight"><pre>_iter <span style="color: #666666">=</span> <span style="color: #008000">iter</span>(obj)             <span style="color: #408080; font-style: italic"># 获取枚举器(iterator)对象</span>
<span style="color: #008000; font-weight: bold">while</span> <span style="color: #666666">1</span>:
   <span style="color: #008000; font-weight: bold">try</span>:
      x <span style="color: #666666">=</span> _iter<span style="color: #666666">.</span>next()        <span style="color: #408080; font-style: italic"># 获取下一个对象</span>
   <span style="color: #008000; font-weight: bold">except</span> <span style="color: #D2413A; font-weight: bold">StopIteration</span>:      <span style="color: #408080; font-style: italic"># 没有更多的对象了</span>
      <span style="color: #008000; font-weight: bold">break</span>
   <span style="color: #408080; font-style: italic"># statements</span>
    <span style="color: #666666">...</span>
</pre></div>
</div><ul class="simple">
<li>任何支持 <tt class="docutils literal"><span class="pre">iter()</span></tt> 和 <tt class="docutils literal"><span class="pre">next()</span></tt> 的对象都被称为 <strong>可枚举</strong> (iterable) 对象</li>
</ul>
</div>
<div class="section" id="id2">
<h4>如何支持枚举</h4>
<ul class="simple">
<li>用户自定义对象可以支持枚举操作</li>
<li>比如：倒计数...</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; for x in countdown(10):
...     print x,
...
10 9 8 7 6 5 4 3 2 1
&gt;&gt;&gt;
</pre>
<ul class="simple">
<li>要做到这点，你只要让该对象拥有 <tt class="docutils literal"><span class="pre">__iter__()</span></tt> 和 <tt class="docutils literal"><span class="pre">next()</span></tt></li>
<li>比如：</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">class</span> <span style="color: #0000FF; font-weight: bold">countdown</span>(<span style="color: #008000">object</span>):
   <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">__init__</span>(<span style="color: #008000">self</span>, start):
       <span style="color: #008000">self</span><span style="color: #666666">.</span>count <span style="color: #666666">=</span> start
   <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">__iter__</span>(<span style="color: #008000">self</span>):
       <span style="color: #008000; font-weight: bold">return</span> <span style="color: #008000">self</span>
   <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">next</span>(<span style="color: #008000">self</span>):
       <span style="color: #008000; font-weight: bold">if</span> <span style="color: #008000">self</span><span style="color: #666666">.</span>count <span style="color: #666666">&lt;=0</span>:
           <span style="color: #008000; font-weight: bold">raise</span> <span style="color: #D2413A; font-weight: bold">StopIteration</span>
       r <span style="color: #666666">=</span> <span style="color: #008000">self</span><span style="color: #666666">.</span>count
       <span style="color: #008000">self</span><span style="color: #666666">.</span>count <span style="color: #666666">-=</span> <span style="color: #666666">1</span>
       <span style="color: #008000; font-weight: bold">return</span> r
</pre></div>
</div></div>
<div class="section" id="id3">
<h4>枚举示例</h4>
<ul class="simple">
<li>应用举例：</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; c = countdown(5)
&gt;&gt;&gt; for i in c:
...     print i,
...
...
5 4 3 2 1
&gt;&gt;&gt;
</pre>
</div>
<div class="section" id="generators">
<h4>Generators</h4>
<ul class="simple">
<li>generator是用来生成一系列结果而非单一值的函数</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">countdown</span>(n):
   <span style="color: #008000; font-weight: bold">while</span> n <span style="color: #666666">&gt;</span> <span style="color: #666666">0</span>:
       <span style="color: #008000; font-weight: bold">yield</span> n
       n <span style="color: #666666">-=</span> <span style="color: #666666">1</span>
</pre></div>
</div><pre class="doctest-block">
&gt;&gt;&gt; for i in countdown(5):
...     print i,
...
5 4 3 2 1
&gt;&gt;&gt;
</pre>
<ul class="simple">
<li>该函数通过 <tt class="docutils literal"><span class="pre">yield</span></tt> 语句生成了一系列的值而非单一值</li>
<li>与普通函数的行为迥异</li>
<li>调用一个generator函数会创建一个 <tt class="docutils literal"><span class="pre">generator</span></tt> 对象。但是，它<strong>并未</strong>开始执行该函数。</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">countdown</span>(n):
   <span style="color: #008000; font-weight: bold">print</span> <span style="color: #BA2121">&quot;Counting down from&quot;</span>, n
   <span style="color: #008000; font-weight: bold">while</span> n <span style="color: #666666">&gt;</span> <span style="color: #666666">0</span>:
       <span style="color: #008000; font-weight: bold">yield</span> n
       n <span style="color: #666666">-=</span> <span style="color: #666666">1</span>
</pre></div>
</div><pre class="doctest-block">
&gt;&gt;&gt; x = countdown(10)   #注意调用该函数此时并未返回函数中print语句的内容
&gt;&gt;&gt; x
&lt;generator object at 0x58490&gt;
&gt;&gt;&gt;
</pre>
</div>
<div class="section" id="generator">
<h4>Generator 函数</h4>
<ul class="simple">
<li>函数在被调用 <tt class="docutils literal"><span class="pre">next()</span></tt> 时才执行</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; x = countdown(10)
&gt;&gt;&gt; x
&lt;generator object at 0x58490&gt;
&gt;&gt;&gt; x.next()
Counting down from 10   #函数此时才开始执行
10
&gt;&gt;&gt;
</pre>
<p><tt class="docutils literal"><span class="pre">yield</span></tt> 生成的一个值，但立即暂停了函数的运行</p>
<ul class="simple">
<li>函数在下一次被调用 <tt class="docutils literal"><span class="pre">next()</span></tt> 时继续运行</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; x.next()
9
&gt;&gt;&gt; x.next()
8
&gt;&gt;&gt;
</pre>
<ul class="simple">
<li>当 <tt class="docutils literal"><span class="pre">generator</span></tt> 返回 <cite>StopIteration</cite> exception 时，枚举结束</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; x.next()
1
&gt;&gt;&gt; x.next()
Traceback (most recent call last):
    File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
StopIteration
&gt;&gt;&gt;
</pre>
<ul class="simple">
<li>generator函数的一大功用是能非常便利的编写获得一个 <tt class="docutils literal"><span class="pre">iterator</span></tt></li>
<li>你不必再去关心神马枚举协议（比如 .next, .__iter__, 诸如此类）</li>
<li>轻松搞定</li>
</ul>
</div>
<div class="section" id="generators-iterators">
<h4>Generators 与 Iterators 的对比</h4>
<ul class="simple">
<li>generator 函数与支持枚举的对象略有不同</li>
<li>generator 只支持 <strong>一次性操作</strong> 。我们可以一次性的枚举遍历所有生成的数据。但如果希望再做一次，我们就必须再次调用这个generator函数。</li>
<li>这与list就不一样了，我们可以任意次数的枚举遍历一个list</li>
</ul>
</div>
<div class="section" id="id4">
<h4>Generator 表达式</h4>
<ul class="simple">
<li>基本上就是一个生成器版本的列表推导式(list comprehension)</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; a = [1,2,3,4]
&gt;&gt;&gt; b = (2*x for x in a)
&gt;&gt;&gt; b
&lt;generator object at 0x58760&gt;
&gt;&gt;&gt; for i in b: print b,
...
2 4 6 8
&gt;&gt;&gt;
</pre>
<ul>
<li><p class="first">该循环遍历一系列的对象并分别处理它们</p>
</li>
<li><p class="first">结果的值是通过generator一次一个生成出来的</p>
</li>
<li><dl class="first docutils">
<dt>与列表推导式的重要不同是</dt>
<dd><ul class="first last simple">
<li>不会构建一个列表</li>
<li>唯一用途是遍历枚举</li>
<li>一旦被消费，无法重用</li>
</ul>
</dd>
</dl>
</li>
<li><p class="first">举例：</p>
</li>
</ul>
<pre class="doctest-block">
&gt;&gt;&gt; a = [1, 2, 3, 4]
&gt;&gt;&gt; b = [2*x for x in a]
&gt;&gt;&gt; b
[2, 4, 6, 8]
&gt;&gt;&gt; c = (2*x for x in a)
&lt;generator object at 0x58760&gt;
&gt;&gt;&gt;
</pre>
<ul>
<li><p class="first">一般语法:</p>
<dl class="docutils">
<dt>(expression for i in s if cond1</dt>
<dd><p class="first last">for j in t if cond2
...
if condfinal)</p>
</dd>
</dl>
</li>
<li><p class="first">意思是：</p>
<dl class="docutils">
<dt>for i in s:</dt>
<dd><dl class="first last docutils">
<dt>if cond1:</dt>
<dd><dl class="first last docutils">
<dt>for j in t:</dt>
<dd><dl class="first last docutils">
<dt>if cond2:</dt>
<dd><p class="first last">...
if condfinal: yield expression</p>
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</li>
</ul>
</div>
<div class="section" id="id5">
<h4>语法的注意事项</h4>
<ul class="simple">
<li>如果将其用于一个函数的唯一参数，其括号可以不写</li>
<li>比如：</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000">sum</span>(x<span style="color: #666666">*</span>x <span style="color: #008000; font-weight: bold">for</span> x <span style="color: #AA22FF; font-weight: bold">in</span> s)
</pre></div>
</div></div>
<div class="section" id="id6">
<h4>小结</h4>
<ul class="simple">
<li>我们目前有两种创建generator对象的方法</li>
<li>Generator函数：</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">countdown</span>(n):
    <span style="color: #008000; font-weight: bold">while</span> n <span style="color: #666666">&gt;</span> <span style="color: #666666">0</span>:
        <span style="color: #008000; font-weight: bold">yield</span> n
        n <span style="color: #666666">-=</span> <span style="color: #666666">1</span>
</pre></div>
</div><ul class="simple">
<li>Generator 表达式</li>
</ul>
<div class="codeblock"><div class="highlight"><pre>squares <span style="color: #666666">=</span> (x<span style="color: #666666">*</span>x <span style="color: #008000; font-weight: bold">for</span> x <span style="color: #AA22FF; font-weight: bold">in</span> s)
</pre></div>
</div><ul class="simple">
<li>用这两种方法我们都可以获得一个可以产生值的对象，一般我们会在for循环中“消费”它</li>
</ul>
</div>
</div>
<div class="section" id="id7">
<h3>第二部分：处理数据文件</h3>
<div class="section" id="id8">
<h4>编程任务</h4>
<table border="1" class="docutils">
<colgroup>
<col width="100%" />
</colgroup>
<tbody valign="top">
<tr><td>将Appache网络服务器的log文件中的最后一列的值
相加以计算总共传输了多少字节的数据。</td>
</tr>
</tbody>
</table>
<div class="line-block">
<div class="line">81.107.39.38 -  ...   &quot;GET    /ply/ http/1.1&quot; 200 7587</div>
<div class="line">81.107.39.38 -  ...   &quot;GET    /favicon.ico htTP/1.1&quot; 404 133</div>
<div class="line">81.107.39.38 -  ...   &quot;GET    /ply/bookplug.gif HTTP/1.1&quot; 200 2390</div>
<div class="line">81.107.39.38 -  ...   &quot;GET    /ply/ply.html hTTP/1.1&quot; 200 97238</div>
<div class="line">81.107.39.38 -  ...   &quot;GET    /ply/example.html HTTP/1.1&quot; 200 2359</div>
<div class="line">66.249.72.134 - ...   &quot;GET    /index.html httP/1.1&quot; 200 4447</div>
</div>
<p>要注意的是这个log文件可能会很大，或许好几个Gbytes</p>
</div>
<div class="section" id="log">
<h4>Log 文件</h4>
<ul>
<li><p class="first">每一行的log看起来是这样的：</p>
<p>81.107.39.38 -  ...   &quot;GET    /ply/bookplug.gif HTTP/1.1&quot; 200 2390</p>
</li>
<li><p class="first">字节数显示在最后一列</p>
</li>
</ul>
<div class="codeblock"><div class="highlight"><pre>bytestr <span style="color: #666666">=</span> line<span style="color: #666666">.</span>rsplit(<span style="color: #008000">None</span>, <span style="color: #666666">1</span>)[<span style="color: #666666">1</span>]
</pre></div>
</div><ul>
<li><p class="first">它要么是一个数字要么是一个值缺失标志(-)</p>
<p>81.107.39.38 -   ...  &quot;GET /ply/ HTTP/1.1&quot; 304 -</p>
</li>
<li><p class="first">类型转换</p>
</li>
</ul>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">if</span> bytestr <span style="color: #666666">!=</span> <span style="color: #BA2121">&#39;-&#39;</span>:
    bytes <span style="color: #666666">=</span> <span style="color: #008000">int</span>(bytestr)
</pre></div>
</div></div>
<div class="section" id="id9">
<h4>一个非-Generator 的解决方案</h4>
<ul class="simple">
<li>仅仅简单的使用一个for循环</li>
</ul>
<div class="codeblock"><div class="highlight"><pre>wwwlog <span style="color: #666666">=</span> <span style="color: #008000">open</span>(<span style="color: #BA2121">&quot;access-log&quot;</span>)
total <span style="color: #666666">=</span> <span style="color: #666666">0</span>
<span style="color: #008000; font-weight: bold">for</span> line <span style="color: #AA22FF; font-weight: bold">in</span> wwwlog:
    bytestr <span style="color: #666666">=</span> line<span style="color: #666666">.</span>rsplit(<span style="color: #008000">None</span>, <span style="color: #666666">1</span>)[<span style="color: #666666">1</span>]
    <span style="color: #008000; font-weight: bold">if</span> bytestr <span style="color: #666666">!=</span> <span style="color: #BA2121">&#39;-&#39;</span>:
        total <span style="color: #666666">+=</span> <span style="color: #008000">int</span>(bytestr)

<span style="color: #008000; font-weight: bold">print</span> <span style="color: #BA2121">&quot;Total&quot;</span>, total
</pre></div>
</div><ul class="simple">
<li>我们一行一行的读取值并更新汇总数据</li>
<li>可是，这个程序竟然运行了90秒钟...</li>
</ul>
</div>
<div class="section" id="id10">
<h4>一个Generator的解决方案</h4>
<ul class="simple">
<li>我们会用到一些generator表达式</li>
</ul>
<div class="codeblock"><div class="highlight"><pre>wwwlog <span style="color: #666666">=</span> <span style="color: #008000">open</span>(<span style="color: #BA2121">&quot;access-log&quot;</span>)
bytecolumn <span style="color: #666666">=</span> (line<span style="color: #666666">.</span>rsplit(<span style="color: #008000">None</span>, <span style="color: #666666">1</span>)[<span style="color: #666666">1</span>] <span style="color: #008000; font-weight: bold">for</span> line <span style="color: #AA22FF; font-weight: bold">in</span> wwwlog)
bytes <span style="color: #666666">=</span> (<span style="color: #008000">int</span>(x) <span style="color: #008000; font-weight: bold">for</span> x <span style="color: #AA22FF; font-weight: bold">in</span> bytecolumn <span style="color: #008000; font-weight: bold">if</span> x <span style="color: #666666">!=</span> <span style="color: #BA2121">&#39;-&#39;</span>)
<span style="color: #008000; font-weight: bold">print</span> <span style="color: #BA2121">&quot;Total&quot;</span>, <span style="color: #008000">sum</span>(bytes)
</pre></div>
</div><ul>
<li><dl class="first docutils">
<dt>大不一样啊！</dt>
<dd><ul class="first last simple">
<li>更少的代码</li>
<li>完全不一样的编程风格</li>
</ul>
</dd>
</dl>
</li>
</ul>
</div>
<div class="section" id="generators-pipeline">
<h4>Generators用做管道(Pipeline)</h4>
<ul class="simple">
<li>要理解这个解决方案，我们可以把它想象成一个数据处理管道</li>
</ul>
<div class="codeblock"><div class="highlight"><pre>              +--------+    +------------+    +-------+    +-------+
access-log -&gt; | wwwlog | -&gt; | bytecolumn | -&gt; | bytes | -&gt; | sum() | -&gt; total
              +--------+    +------------+    +-------+    +-------+
</pre></div>
</div><p>未完待续...</p>
</div>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;submitHeadline=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;title=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;title=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;title=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;bm_description=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;T=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;title=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;title=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator+@+http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fdive-into-generator&amp;t=%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3+Generator" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/python/dive-into-generator/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何在Open ERP项目开发中使用bzr工具</title>
		<link>http://blog.shine-it.net/openerp/how-to-use-bzr-tool-in-openerp-developing</link>
		<comments>http://blog.shine-it.net/openerp/how-to-use-bzr-tool-in-openerp-developing#comments</comments>
		<pubDate>Thu, 23 Dec 2010 14:15:32 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Open ERP]]></category>
		<category><![CDATA[bzr]]></category>
		<category><![CDATA[openerp]]></category>
		<category><![CDATA[vcs]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/opensource/how-to-use-bzr-tool-in-openerp-developing</guid>
		<description><![CDATA[问题说明 本文是以Open ERP项目开发来介绍bzr工具的使用，文中介绍的方法也适用于其他的软件项目开发。 Open ERP的项目开发使用了 Launchpad 项目管理平台，其代码的版本管理使用的是bzr工具。我们大概已经知道bzr是一个分布式版本控制工具。那么，对于类似Open ERP这样的大型项目，如何才能充分发挥bzr分布式的优势使代码版本历史清晰，协作开发方便呢？本文通过作者对Open ERP的服务器代码管理的实例来介绍一种较好的使用bzr工具的方法。 Open ERP服务器项目在 Launchpad 上的位置是： http://launchpad.net/openobject-server , 其目前包含三个系列: 4.2版本系列， 5.0版本系列， Trunk版本系列（其包含即将发布的6.0版本）。 一般来说我们对其只有只读权限，就是说我们可以下载代码并修改，但是无法直接提交到其在 Launchpad 上的版本库中。当然我们可以在 Launchpad 上注册自己的修改分支，并通过申请合并的方式，将修改合并到官方分支中. 现在假设我们工作在Trunk版本上，我们可以使用以下命令来创建本地分支： bzr branch lp:openobject-server server 这样在本地的server目录下就有了Open ERP服务器的完整本地分支了。我们可以直接在这个分支上做代码的调整改进并提交（Commit）到这个本地分支，同时还可以将上游代码的修改合并（Merge）到本地分支。但是，如果我们希望对之前的某个消除bug的代码改进合并到官方的分支中就不是很容易了，因为我们的本地版本已经混合了我们的多个修改了，下面介绍的方法可以让我们提交一个“干净”的针对某bug的代码改进分支，并请求合并到官方分支中 解决方法 创建共享版本库 因为将要使用的是多个任务分支（Task branch)或称为特性分支（Feature branch）的方法。我们希望每个分支中的信息在版本库中共享而不是在每个分支中创建单独的版本历史信息，这样做法的好处是大大的节省了磁盘的使用空间。创建的方法： bzr init-repo --no-trees server-repo cd server-repo 上面的命令表示创建一个版本库， --no-trees 选项表示在其中创建的分支将不包含工作树。 创建上游代码的镜像分支 创建一个与上游代码完全一致的本地分支，我们的任何修改都不会提交到该分支，保证该分支“干净” bzr branch lp:openobject-server server 上面的命令与上一节中提到的创建本地分支的方法完全一样，但是你会发现该命令在本地只创建了一个server目录，目录中并无内容（其实包含一个隐含目录.bzr),这是因为其所在的版本库使用了 --no-trees 选项，这样在创建分支时就不会生成工作树。 如果你之前已经创建了本地分支，现在想使其使用共享版本库，可以将其拷贝到版本库目录下，并进入分支目录中，输入以下命令： [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<div class="section" id="id1">
<h3>问题说明</h3>
<p>本文是以Open ERP项目开发来介绍bzr工具的使用，文中介绍的方法也适用于其他的软件项目开发。</p>
<p>Open ERP的项目开发使用了 <a class="reference external" href="http://launchpad.net">Launchpad</a> 项目管理平台，其代码的版本管理使用的是bzr工具。我们大概已经知道bzr是一个分布式版本控制工具。那么，对于类似Open ERP这样的大型项目，如何才能充分发挥bzr<strong>分布式</strong>的优势使代码版本历史清晰，协作开发方便呢？本文通过作者对Open ERP的服务器代码管理的实例来介绍一种较好的使用bzr工具的方法。</p>
<span id="more-710"></span>
<p>Open ERP服务器项目在 <a class="reference external" href="http://launchpad.net">Launchpad</a> 上的位置是： <a class="reference external" href="http://launchpad.net/openobject-server">http://launchpad.net/openobject-server</a> , 其目前包含三个系列:</p>
<ul class="simple">
<li>4.2版本系列，</li>
<li>5.0版本系列，</li>
<li>Trunk版本系列（其包含即将发布的6.0版本）。</li>
</ul>
<p>一般来说我们对其只有只读权限，就是说我们可以下载代码并修改，但是无法直接提交到其在 <a class="reference external" href="http://launchpad.net">Launchpad</a> 上的版本库中。当然我们可以在 <a class="reference external" href="http://launchpad.net">Launchpad</a> 上注册自己的修改分支，并通过申请合并的方式，将修改合并到官方分支中. 现在假设我们工作在Trunk版本上，我们可以使用以下命令来创建本地分支：</p>
<div class="codeblock"><div class="highlight"><pre>bzr branch lp:openobject-server server
</pre></div>
</div><p>这样在本地的server目录下就有了Open ERP服务器的完整本地分支了。我们可以直接在这个分支上做代码的调整改进并提交（Commit）到这个本地分支，同时还可以将上游代码的修改合并（Merge）到本地分支。但是，如果我们希望对之前的某个消除bug的代码改进合并到官方的分支中就不是很容易了，因为我们的本地版本已经混合了我们的多个修改了，下面介绍的方法可以让我们提交一个“干净”的针对某bug的代码改进分支，并请求合并到官方分支中</p>
</div>
<div class="section" id="id2">
<h3>解决方法</h3>
<div class="section" id="id3">
<h4>创建共享版本库</h4>
<p>因为将要使用的是多个任务分支（Task branch)或称为特性分支（Feature branch）的方法。我们希望每个分支中的信息在版本库中共享而不是在每个分支中创建单独的版本历史信息，这样做法的好处是大大的节省了磁盘的使用空间。创建的方法：</p>
<div class="codeblock"><div class="highlight"><pre>bzr init-repo --no-trees server-repo
<span style="color: #008000">cd </span>server-repo
</pre></div>
</div><p>上面的命令表示创建一个版本库， <tt class="docutils literal"><span class="pre">--no-trees</span></tt> 选项表示在其中创建的分支将不包含工作树。</p>
</div>
<div class="section" id="id4">
<h4>创建上游代码的镜像分支</h4>
<p>创建一个与上游代码完全一致的本地分支，我们的任何修改都不会提交到该分支，保证该分支“干净”</p>
<div class="codeblock"><div class="highlight"><pre>bzr branch lp:openobject-server server
</pre></div>
</div><p>上面的命令与上一节中提到的创建本地分支的方法完全一样，但是你会发现该命令在本地只创建了一个server目录，目录中并无内容（其实包含一个隐含目录.bzr),这是因为其所在的版本库使用了 <tt class="docutils literal"><span class="pre">--no-trees</span></tt> 选项，这样在创建分支时就不会生成工作树。</p>
<p>如果你之前已经创建了本地分支，现在想使其使用共享版本库，可以将其拷贝到版本库目录下，并进入分支目录中，输入以下命令：</p>
<div class="codeblock"><div class="highlight"><pre>bzr reconfigure --use-shared
</pre></div>
</div><p>这样该分支就会使用共享版本库来管理历史版本信息了。</p>
</div>
<div class="section" id="id5">
<h4>创建任务分支</h4>
<p>现在我们可以创建之前提到的任务或特性分支了，方法是（假设我们现在在版本库目录server-repo下）：</p>
<div class="codeblock"><div class="highlight"><pre>bzr branch server trunk
</pre></div>
</div><p>这样我们就基于镜像分支server创建了一个任务分支trunk。我们的修改工作可以在trunk中进行，让镜像分支保持“纯洁”，但是这个trunk分支仍然没有工作树，面对一团空气我们如何做代码修改呀？</p>
</div>
<div class="section" id="lightweight-checkout">
<h4>轻型检出(lightweight checkout)</h4>
<div class="codeblock"><div class="highlight"><pre>bzr checkout --lightweight trunk myserver
<span style="color: #008000">cd </span>myserver
<span style="color: #408080; font-style: italic">#hack hack</span>
bzr commit -m<span style="color: #BA2121">&#39;blah blah&#39;</span>
</pre></div>
</div><p>以上命令将从trunk分支中检出代码在myserver目录中创建工作树，因为使用了 <tt class="docutils literal"><span class="pre">lightweight</span></tt> 选项，所以检出的工作树中不包含任何版本信息，全部通过访问其绑定的分支来获取，这样就又进一步减少了对磁盘的占用。</p>
</div>
<div class="section" id="switch">
<h4>轻型检出的切换(switch)</h4>
<p>假设我们发现了一个bug，这时就可以为解决这个bug创建一个任务分支。因为我们使用了共享版本库，所以创建任务分支是很“轻型”的，很快速也很少占用磁盘空间。对解决不同的bug，或添加不同的功能特性我们都可以用这种快速创建任务分支的办法。这种分支非常的“干净”，只包含针对特定任务的代码改变，非常适合提交给官方分支要求合并。</p>
<div class="codeblock"><div class="highlight"><pre>bzr branch ../server ../bug-fix-1
bzr switch ../bug-fix-1
<span style="color: #408080; font-style: italic">#hack hack</span>
bzr commit -m<span style="color: #BA2121">&#39;bug1 fixed&#39;</span>
bzr switch ../trunk
</pre></div>
</div><p>以上命令假设我们还在 <tt class="docutils literal"><span class="pre">myserver</span></tt> 这个工作树目录下，创建了 <tt class="docutils literal"><span class="pre">bug-fix-1</span></tt> 这个任务分支，并用 <tt class="docutils literal"><span class="pre">bzr</span> <span class="pre">switch</span> <span class="pre">../bug-fix-1</span></tt> 命令切换到这个分支，工作树的内容也会随之改变，Bug解决后，提交改变，并用 switch 切换回 trunk分支。用这种方法在不同的分支切换，不必为每个分支单独创建工作树，使得磁盘空间得到有效的节约，更重要的是我们可以只在一个目录下工作，不用换来换去。</p>
</div>
<div class="section" id="bug">
<h4>bug解决方案的提交</h4>
<p>解决一个bug后我们希望提交给Open ERP核心开发人员，并将其合并到官方分支中。那你首先要在 <a class="reference external" href="http://launchpad.net">Launchpad</a> 上注册一个帐号，提交ssh公钥，并且加入 <a class="reference external" href="http://launchpad.net/~openerp-community">openerp-community</a> 或  <a class="reference external" href="http://launchpad.net/~openerp-chinese-team">openerp-chinese-team</a>  团队（点击左边给出的链接，点击 &quot;Join Team&quot; 按钮加入。 <strong>注:</strong> 加入  <a class="reference external" href="http://launchpad.net/~openerp-chinese-team">openerp-chinese-team</a>  就会自动加入 <a class="reference external" href="http://launchpad.net/~openerp-community">openerp-community</a> 团队。）</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000">cd</span> ../bug-fix-1
bzr launchpad-login userid
bzr push lp:~openerp-chinese-team/openobject-server/my-bug-fix
</pre></div>
</div><p><tt class="docutils literal"><span class="pre">bzr</span> <span class="pre">launchpad-login</span> <span class="pre">userid</span></tt> 命令只需要输入一次，以后不用输了，其中userid就是你在 <a class="reference external" href="http://launchpad.net">Launchpad</a> 上注册的帐号。当你输入完成上面这些命令后，就会在 <a class="reference external" href="http://launchpad.net/~openerp-chinese-team">openerp-chinese-team</a>  的code页面下创建该“远端分支”（remote branch), 同时在 <a class="reference external" href="http://code.launchpad.net/openobject-server">http://code.launchpad.net/openobject-server</a> 下也会显示你的分支。在这个“远端分支”的页面下你可以请求合并（Propose Merge）到官方分支中。这里要注意push命令中，~openerp-chinese-team是团队名称或你注册的用户名，openobject-server是所关联的项目，my-bug-fix是你给这个分支起的名字。</p>
</div>
<div class="section" id="id6">
<h4>代码更新</h4>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000">cd</span> ../server
bzr pull
</pre></div>
</div><p>server分支更新了来自上游的代码，</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000">cd</span> ../myserver
bzr merge ../server
bzr commit -m<span style="color: #BA2121">&#39;merge official branch&#39;</span>
bzr merge ../bug-fix-1
bzr commit -m<span style="color: #BA2121">&#39;merge bug-fix-1&#39;</span>
</pre></div>
</div><p>以上命令就将上游的更新和bug-fix-1分支的更新合并到了trunk分支</p>
</div>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;submitHeadline=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;title=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;title=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;title=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;bm_description=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;T=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;title=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;title=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7+@+http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fopenerp%2Fhow-to-use-bzr-tool-in-openerp-developing&amp;t=%E5%A6%82%E4%BD%95%E5%9C%A8Open+ERP%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%BF%E7%94%A8bzr%E5%B7%A5%E5%85%B7" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/openerp/how-to-use-bzr-tool-in-openerp-developing/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>使用SOCKS代理服务器转发bzr通信</title>
		<link>http://blog.shine-it.net/linux/tunneling-bzr-connection-through-socks-proxy</link>
		<comments>http://blog.shine-it.net/linux/tunneling-bzr-connection-through-socks-proxy#comments</comments>
		<pubDate>Mon, 12 Jul 2010 03:29:21 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[tsocks]]></category>
		<category><![CDATA[tunneling]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/linux/tunneling-bzr-connection-through-socks-proxy</guid>
		<description><![CDATA[创建SSH SOCKS 服务器 我们知道设置SSH SOCKS 代理服务器是很简单的，只要你有一个远端服务器的ssh帐号，使用下面的命令就可以轻易的创建一个套接字代理服务器。 ssh -fND 6666 ssh_user@ssh_server 它的用途是将应用程序的端口请求通过ssh加密通道动态的转发到远端ssh服务器。比如，我们可以设置firefox使用SOCKS5代理服务器并将端口按上面的命令设置为6666, 这样当我们用firefox浏览网页时（也就是对80端口的访问请求）就被转发到远端ssh服务器上作请求了。因为所有的访问请求经过ssh加密通道，所以用来对付墙还是很得心应手的。 bzr 不支持SOCKS代理服务器转发 因为经常要用bzr版本控制工具同步在launchpad上的项目，但是直截访问launchpad的速度实在太慢了。我发现我在国外租用的ssh服务器访问launchpad的速度非常快，而本地访问ssh服务器的速度也还不错，所以，自然就想到了能不能把bzr通信转发到ssh服务器。很不幸的发现bzr并不支持SOCKS代理服务转发。难不成我们只能忍受bzrlp的龟速，Google一通之后，发现了 tsocks tsocks 如何工作 它的基本原理是： 在加载应用程序之前, tsocks 先加载其共享库 该函数库覆写了内核的 connect() 函数 这样当应用程序发送连接请求时，该请求就被转发给了代理服务器（然后通过加密通道转发到了ssh服务器） 所有这些是通过设置环境变量 LD—RELOAD``的值为 ``/usr/lib/libtsocks.so 来实现的，tsocks 本身只是一个简单的shell包装(wrapper)脚本，所有的转发任务都是由上述的函数库完成。 安装好tsocks后，编辑文件 /etc/tsocks.conf 将已有的所有内容都注释掉，添加下面两行内容: server = 127.0.0.1 server_port = 6666 #设置为你的SSH SOCKS服务器开放的端口 就是这么简单，以后我们只要在运行bzr程序前，运行tsocks就可以使用创建好的SSH SOCKS服务器了: tsocks bzr pull lp:xxxx 这下bzr的访问速度还真是大大的提高了, 其实我们可以用tsocks来实现所有不直接支持SOCKS代理服务的程序。 参考文章：http://www.plenz.com/tunnel-everything 网络书签]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<div class="section" id="ssh-socks">
<h3>创建SSH SOCKS 服务器</h3>
<p>我们知道设置SSH SOCKS 代理服务器是很简单的，只要你有一个远端服务器的ssh帐号，使用下面的命令就可以轻易的创建一个套接字代理服务器。</p>
<div class="codeblock"><div class="highlight"><pre>ssh -fND 6666 ssh_user@ssh_server
</pre></div>
</div><p>它的用途是将应用程序的端口请求通过ssh加密通道动态的转发到远端ssh服务器。比如，我们可以设置firefox使用SOCKS5代理服务器并将端口按上面的命令设置为6666, 这样当我们用firefox浏览网页时（也就是对80端口的访问请求）就被转发到远端ssh服务器上作请求了。因为所有的访问请求经过ssh加密通道，所以用来对付<tt class="docutils literal"><span class="pre">墙</span></tt>还是很得心应手的。</p>
</div>
<div class="section" id="bzr-socks">
<h3>bzr 不支持SOCKS代理服务器转发</h3>
<p>因为经常要用bzr版本控制工具同步在launchpad上的项目，但是直截访问launchpad的速度实在太慢了。我发现我在国外租用的ssh服务器访问launchpad的速度非常快，而本地访问ssh服务器的速度也还不错，所以，自然就想到了能不能把bzr通信转发到ssh服务器。很不幸的发现bzr并不支持SOCKS代理服务转发。难不成我们只能忍受bzrlp的龟速，Google一通之后，发现了 <tt class="docutils literal"><span class="pre">tsocks</span></tt></p>
</div>
<div class="section" id="tsocks">
<h3>tsocks 如何工作</h3>
<p>它的基本原理是：</p>
<ul class="simple">
<li>在加载应用程序之前, <tt class="docutils literal"><span class="pre">tsocks</span></tt> 先加载其共享库</li>
<li>该函数库覆写了内核的 <tt class="docutils literal"><span class="pre">connect()</span></tt> 函数</li>
<li>这样当应用程序发送连接请求时，该请求就被转发给了代理服务器（然后通过加密通道转发到了ssh服务器）</li>
</ul>
<p>所有这些是通过设置环境变量 <tt class="docutils literal"><span class="pre">LD—RELOAD``的值为</span> <span class="pre">``/usr/lib/libtsocks.so</span></tt> 来实现的，tsocks 本身只是一个简单的shell包装(wrapper)脚本，所有的转发任务都是由上述的函数库完成。</p>
<p>安装好tsocks后，编辑文件 <tt class="docutils literal"><span class="pre">/etc/tsocks.conf</span></tt> 将已有的所有内容都注释掉，添加下面两行内容:</p>
<pre class="literal-block">
server = 127.0.0.1
server_port = 6666 #设置为你的SSH SOCKS服务器开放的端口
</pre>
<p>就是这么简单，以后我们只要在运行bzr程序前，运行tsocks就可以使用创建好的SSH SOCKS服务器了:</p>
<pre class="literal-block">
tsocks bzr pull lp:xxxx
</pre>
<p>这下bzr的访问速度还真是大大的提高了, 其实我们可以用tsocks来实现所有不直接支持SOCKS代理服务的程序。</p>
<p>参考文章：http://www.plenz.com/tunnel-everything</p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;submitHeadline=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;title=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;title=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;title=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;bm_description=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;T=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;title=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;title=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1+@+http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Ftunneling-bzr-connection-through-socks-proxy&amp;t=%E4%BD%BF%E7%94%A8SOCKS%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AC%E5%8F%91bzr%E9%80%9A%E4%BF%A1" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/linux/tunneling-bzr-connection-through-socks-proxy/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thinkpad T61 无法检测到路由器</title>
		<link>http://blog.shine-it.net/linux/thinkpad-t61-not-able-to-detect-the-router</link>
		<comments>http://blog.shine-it.net/linux/thinkpad-t61-not-able-to-detect-the-router#comments</comments>
		<pubDate>Sun, 14 Feb 2010 16:10:07 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Channel]]></category>
		<category><![CDATA[regdomain]]></category>
		<category><![CDATA[Wifi]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/linux/thinkpad-t61-not-able-to-detect-the-router</guid>
		<description><![CDATA[缘起 我的笔记本电脑（Thinkpad T61 ）的无线连接总是感觉有点古怪，经常会在无线网络中找不到自家的那台贝尔金路由器，但是却能搜出一堆邻居的路由器，而同时家里的其他电脑访问贝尔金路由器又毫无问题。这应该说明贝尔金路由器的工作是正常的，可是在找不到原因的情况下重启几次路由器，Thinkpad T61又突然能找到这台路由器了。最近被它折腾的超烦，路由器重启了N遍，这边的笔记本就是检测不到。忍无可忍，决定彻底的查查原因。试了几次之后发现当我把路由器的频段（Channel）设置从 自动 改为11及以下的设置后，笔记本电脑总能检测到路由器。问题是终于解决了，可是不能使用路由器上的自动频段选择有点不爽，因为路由器的自动频段选择可以避开繁忙的频段而使用周围环境中较少使用的频段，这样无线信号的干扰就会少一点。而且T61无法使用11以上的频段的原因也没有找到。于是戟起google大法，一通搜索之后终于让我的好奇心得到了满足。 排错过程 我的笔记本上装的是Ubuntu9.10,所以下面的命令都仅适用于Linux。 下面的这个简单的命令实际上一招就能展示我反复试验得出的结论: 就是T61上无法访问11以上的频段，只是不幸的是俺是后来才知道的: iwlist f 这条命令的结果是显示本机无线可连接的所有频段。在我的电脑上不存在12,13,14这些我的G带宽贝尔金路由器所支持的频段。另外还有一些更高的频段是适用于N带宽路由器的，这里不做讨论。通过搜索了解到，Wifi的IEEE802.11的规范中有regdomain这样的地域规范，就是不同地区所能使用的频段数是不同的。对于G带宽来说美国支持1到11, 欧洲多了12, 13, 而亚洲则另外可以使用14. 所以考虑是不是我的笔记本电脑的无线网卡驱动默认了美国的规范，看能不能改成欧洲或亚洲的。网上介绍了N种办法，因为我的Ubuntu9.10 使用CRDA程序来向内核模块通知domain regulatory的信息（即，地域设置规范），最简单的方法就是: sudo aptitude install iw 安装iw 无线网管理程序，然后在 /etc/rc.local 中添加一行如下代码，并重启电脑: iw reg set CN 就是把地域设置为中国。遗憾的是重启电脑后， iwlist f 仍然没有看到久违的12,13,14频段。 lspci 列出了T61使用的是intel 4965 AGN无线模组。再根据该型号来查，原来这个无线模组可能在硬件中设置了美国区，也就是只能使用1到11的频段。至此，我的调查算基本完成，虽然调查并没有为我提供更好的方案，但总算是头绪清爽了，也或许对其他朋友有帮助。另外，对胆大妄为的兄弟可以提供一个进一步的调查方向，就是无线模组的regdomain是纪录在eeprom里的，是可以被擦写修改的，有兄弟饭吃多了，可以往这个方向上再努把力。 网络书签]]></description>
			<content:encoded><![CDATA[
<div class="document">


<!-- -*- mode: rst -*- -->
<div class="section" id="id1">
<h3>缘起</h3>
<p>我的笔记本电脑（Thinkpad T61 ）的无线连接总是感觉有点古怪，经常会在无线网络中找不到自家的那台贝尔金路由器，但是却能搜出一堆邻居的路由器，而同时家里的其他电脑访问贝尔金路由器又毫无问题。这应该说明贝尔金路由器的工作是正常的，可是在找不到原因的情况下重启几次路由器，Thinkpad T61又突然能找到这台路由器了。最近被它折腾的超烦，路由器重启了N遍，这边的笔记本就是检测不到。忍无可忍，决定彻底的查查原因。试了几次之后发现当我把路由器的频段（Channel）设置从 <em>自动</em> 改为11及以下的设置后，笔记本电脑总能检测到路由器。问题是终于解决了，可是不能使用路由器上的自动频段选择有点不爽，因为路由器的自动频段选择可以避开繁忙的频段而使用周围环境中较少使用的频段，这样无线信号的干扰就会少一点。而且T61无法使用11以上的频段的原因也没有找到。于是戟起google大法，一通搜索之后终于让我的好奇心得到了满足。</p>
</div>
<div class="section" id="id2">
<h3>排错过程</h3>
<p>我的笔记本上装的是Ubuntu9.10,所以下面的命令都仅适用于Linux。</p>
<p>下面的这个简单的命令实际上一招就能展示我反复试验得出的结论: 就是T61上无法访问11以上的频段，只是不幸的是俺是后来才知道的:</p>
<pre class="literal-block">
iwlist f
</pre>
<p>这条命令的结果是显示本机无线可连接的所有频段。在我的电脑上不存在12,13,14这些我的G带宽贝尔金路由器所支持的频段。另外还有一些更高的频段是适用于N带宽路由器的，这里不做讨论。通过搜索了解到，Wifi的IEEE802.11的规范中有regdomain这样的地域规范，就是不同地区所能使用的频段数是不同的。对于G带宽来说美国支持1到11, 欧洲多了12, 13, 而亚洲则另外可以使用14. 所以考虑是不是我的笔记本电脑的无线网卡驱动默认了美国的规范，看能不能改成欧洲或亚洲的。网上介绍了N种办法，因为我的Ubuntu9.10 使用CRDA程序来向内核模块通知domain regulatory的信息（即，地域设置规范），最简单的方法就是:</p>
<pre class="literal-block">
sudo aptitude install iw
</pre>
<p>安装iw 无线网管理程序，然后在 <tt class="docutils literal"><span class="pre">/etc/rc.local</span></tt> 中添加一行如下代码，并重启电脑:</p>
<pre class="literal-block">
iw reg set CN
</pre>
<p>就是把地域设置为中国。遗憾的是重启电脑后， <tt class="docutils literal"><span class="pre">iwlist</span> <span class="pre">f</span></tt> 仍然没有看到久违的12,13,14频段。</p>
<pre class="literal-block">
lspci
</pre>
<p>列出了T61使用的是intel 4965 AGN无线模组。再根据该型号来查，原来这个无线模组可能在硬件中设置了美国区，也就是只能使用1到11的频段。至此，我的调查算基本完成，虽然调查并没有为我提供更好的方案，但总算是头绪清爽了，也或许对其他朋友有帮助。另外，对胆大妄为的兄弟可以提供一个进一步的调查方向，就是无线模组的regdomain是纪录在eeprom里的，是可以被擦写修改的，有兄弟饭吃多了，可以往这个方向上再努把力。</p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;submitHeadline=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;title=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;title=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;title=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;bm_description=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;T=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;title=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;title=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8+@+http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Flinux%2Fthinkpad-t61-not-able-to-detect-the-router&amp;t=Thinkpad+T61+%E6%97%A0%E6%B3%95%E6%A3%80%E6%B5%8B%E5%88%B0%E8%B7%AF%E7%94%B1%E5%99%A8" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/linux/thinkpad-t61-not-able-to-detect-the-router/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>对付电信dns劫持的firefox插件</title>
		<link>http://blog.shine-it.net/opensource/dns-hijack-firefox-addon</link>
		<comments>http://blog.shine-it.net/opensource/dns-hijack-firefox-addon#comments</comments>
		<pubDate>Wed, 20 Jan 2010 16:47:56 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[dns hijack]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[noredirect]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/?p=695</guid>
		<description><![CDATA[最近被电信的DNS劫持搞得烦不胜烦，动不动就被绑架到114search.118114.cn这个恶心的网址上。今天在firefox的addons网站上闲逛还真让我找到了一个很不错的插件来对付这种绑你没商量的强盗行为。 闲话少叙，这个插件的下载位置在：https://addons.mozilla.org/zh-CN/firefox/addon/11787 注：我直接安装插件碰到了一个错误，是因为软件标明的firefox所需版本号有问题，你如果碰到同样的问题可以下载本文所带的附件，解压后拖到firefox里就可以安装了。 安装后，请到firefox的工具-附加组件下找到该插件并点击“首选项“ 里面已经设置了对一些网址重定向的处理规则，它们无非就是用正则表达式来过滤需要处理的网址，对114search我们设定如下： wola, 你不再被流氓们敲闷棍，拉到恶心的地方去了。对于输入错误的网址也会正确显示DNS error 错误信息了。 又案：DNS劫持已不是什么新鲜的东东了，很多ISP为了广告流量都在做这样严重违反互联网规则的事，包括被网友们推崇的openDNS。关于openDNS和GoogleDNS，请参见这篇好文：http://www.chinaz.com/Webmaster/Club/120Q004632009.html no-redirect插件下载：no-redirect.xpi 网络书签]]></description>
			<content:encoded><![CDATA[<p>最近被电信的DNS劫持搞得烦不胜烦，动不动就被绑架到114search.118114.cn这个恶心的网址上。今天在firefox的addons网站上闲逛还真让我找到了一个很不错的插件来对付这种绑你没商量的强盗行为。</p>
<p>闲话少叙，这个插件的下载位置在：<a href="https://addons.mozilla.org/zh-CN/firefox/addon/11787">https://addons.mozilla.org/zh-CN/firefox/addon/11787</a><br />
<strong>注：</strong>我直接安装插件碰到了一个错误，是因为软件标明的firefox所需版本号有问题，你如果碰到同样的问题可以下载本文所带的附件，解压后拖到firefox里就可以安装了。</p>
<p>安装后，请到firefox的工具-附加组件下找到该插件并点击“首选项“</p>
<p><a href="http://blog.shine-it.net/wp-content/uploads/2010/01/noredirect1.png"><img class="aligncenter size-full wp-image-696" title="noredirect1" src="http://blog.shine-it.net/wp-content/uploads/2010/01/noredirect1.png" alt="" width="522" height="412" /></a></p>
<p>里面已经设置了对一些网址重定向的处理规则，它们无非就是用正则表达式来过滤需要处理的网址，对114search我们设定如下：</p>
<p><a href="http://blog.shine-it.net/wp-content/uploads/2010/01/NoRedirect-Settings_002.png"><img class="aligncenter size-full wp-image-697" title="NoRedirect Settings_002" src="http://blog.shine-it.net/wp-content/uploads/2010/01/NoRedirect-Settings_002.png" alt="Noredirect Settings" width="681" height="495" /></a></p>
<p>wola, 你不再被流氓们敲闷棍，拉到恶心的地方去了。对于输入错误的网址也会正确显示DNS error 错误信息了。</p>
<p>又案：DNS劫持已不是什么新鲜的东东了，很多ISP为了广告流量都在做这样严重违反互联网规则的事，包括被网友们推崇的openDNS。关于openDNS和GoogleDNS，请参见这篇好文：<a href="http://www.chinaz.com/Webmaster/Club/120Q004632009.html">http://www.chinaz.com/Webmaster/Club/120Q004632009.html</a></p>
<p>no-redirect插件下载：<a href="http://blog.shine-it.net/wp-content/uploads/2010/01/no-redirect.xpi_.zip">no-redirect.xpi</a></p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;submitHeadline=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;title=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;title=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;title=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;bm_description=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;T=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;title=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;title=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6+@+http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fopensource%2Fdns-hijack-firefox-addon&amp;t=%E5%AF%B9%E4%BB%98%E7%94%B5%E4%BF%A1dns%E5%8A%AB%E6%8C%81%E7%9A%84firefox%E6%8F%92%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/opensource/dns-hijack-firefox-addon/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python食谱-1.25.在Unix终端上格式化显示HTML文本</title>
		<link>http://blog.shine-it.net/python/converting-html-documents-to-text-on-a-unix-terminal</link>
		<comments>http://blog.shine-it.net/python/converting-html-documents-to-text-on-a-unix-terminal#comments</comments>
		<pubDate>Wed, 14 Oct 2009 11:29:20 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[formatter]]></category>
		<category><![CDATA[htmllib]]></category>
		<category><![CDATA[Python食谱]]></category>
		<category><![CDATA[tput]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/python/converting-html-documents-to-text-on-a-unix-terminal</guid>
		<description><![CDATA[原文作者:Brent Burley, Mark Moraes 中文翻译:Tony (digitalsatori) 问题 如何才能在Unix终端上显示HTML文本，使其可以表现粗体和下划线。 解决方案 最简单的方法是编制一个过滤脚本，从标准输入获取HTML然后在标准输出文本和终端控制符。因为本配方针对得唯一对象是Unix, 我们可以通过Unix命令 tput 来获取需要的终端控制符。具体方法是使用Python标准库中os模块中得popen函数来启动tput。 #!/usr/bin/env python import sys, os, htmllib, formatter # use Unix tput to get the escape sequences for bold, underline, reset set_bold = os.popen(&#39;tput bold&#39;).read( ) set_underline = os.popen(&#39;tput smul&#39;).read( ) perform_reset = os.popen(&#39;tput sgr0&#39;).read( ) class TtyFormatter(formatter.AbstractFormatter): &#39;&#39;&#39; a formatter that keeps [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">

<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">原文作者:</th><td class="field-body">Brent Burley, Mark Moraes</td>
</tr>
<tr class="field"><th class="docinfo-name">中文翻译:</th><td class="field-body">Tony (digitalsatori)</td>
</tr>
</tbody>
</table>
<!-- -*- mode: rst -*- -->
<div class="section" id="id1">
<h3>问题</h3>
<p>如何才能在Unix终端上显示HTML文本，使其可以表现粗体和下划线。</p>
</div>
<div class="section" id="id2">
<h3>解决方案</h3>
<p>最简单的方法是编制一个过滤脚本，从标准输入获取HTML然后在标准输出文本和终端控制符。因为本配方针对得唯一对象是Unix, 我们可以通过Unix命令 <tt class="docutils literal"><span class="pre">tput</span></tt> 来获取需要的终端控制符。具体方法是使用Python标准库中os模块中得popen函数来启动tput。</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #408080; font-style: italic">#!/usr/bin/env python</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">sys</span><span style="color: #666666">,</span> <span style="color: #0000FF; font-weight: bold">os</span><span style="color: #666666">,</span> <span style="color: #0000FF; font-weight: bold">htmllib</span><span style="color: #666666">,</span> <span style="color: #0000FF; font-weight: bold">formatter</span>
<span style="color: #408080; font-style: italic"># use Unix tput to get the escape sequences for bold, underline, reset</span>
set_bold <span style="color: #666666">=</span> os<span style="color: #666666">.</span>popen(<span style="color: #BA2121">&#39;tput bold&#39;</span>)<span style="color: #666666">.</span>read( )
set_underline <span style="color: #666666">=</span> os<span style="color: #666666">.</span>popen(<span style="color: #BA2121">&#39;tput smul&#39;</span>)<span style="color: #666666">.</span>read( )
perform_reset <span style="color: #666666">=</span> os<span style="color: #666666">.</span>popen(<span style="color: #BA2121">&#39;tput sgr0&#39;</span>)<span style="color: #666666">.</span>read( )
<span style="color: #008000; font-weight: bold">class</span> <span style="color: #0000FF; font-weight: bold">TtyFormatter</span>(formatter<span style="color: #666666">.</span>AbstractFormatter):
    <span style="color: #BA2121; font-style: italic">&#39;&#39;&#39; a formatter that keeps track of bold and italic font states, and</span>
<span style="color: #BA2121; font-style: italic">        emits terminal control sequences accordingly.</span>
<span style="color: #BA2121; font-style: italic">    &#39;&#39;&#39;</span>
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_</span> _init_ _(<span style="color: #008000">self</span>, writer):
        <span style="color: #408080; font-style: italic"># first, as usual, initialize the superclass</span>
        formatter<span style="color: #666666">.</span>AbstractFormatter<span style="color: #666666">.</span>_ _init_ _(<span style="color: #008000">self</span>, writer)
        <span style="color: #408080; font-style: italic"># start with neither bold nor italic, and no saved font state</span>
        <span style="color: #008000">self</span><span style="color: #666666">.</span>fontState <span style="color: #666666">=</span> <span style="color: #008000">False</span>, <span style="color: #008000">False</span>
        <span style="color: #008000">self</span><span style="color: #666666">.</span>fontStack <span style="color: #666666">=</span> [  ]
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">push_font</span>(<span style="color: #008000">self</span>, font):
        <span style="color: #408080; font-style: italic"># the `font&#39; tuple has four items, we only track the two flags</span>
        <span style="color: #408080; font-style: italic"># about whether italic and bold are active or not</span>
        size, is_italic, is_bold, is_tt <span style="color: #666666">=</span> font
        <span style="color: #008000">self</span><span style="color: #666666">.</span>fontStack<span style="color: #666666">.</span>append((is_italic, is_bold))
        <span style="color: #008000">self</span><span style="color: #666666">.</span>_updateFontState( )
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">pop_font</span>(<span style="color: #008000">self</span>, <span style="color: #666666">*</span>args):
        <span style="color: #408080; font-style: italic"># go back to previous font state</span>
        <span style="color: #008000; font-weight: bold">try</span>:
            <span style="color: #008000">self</span><span style="color: #666666">.</span>fontStack<span style="color: #666666">.</span>pop( )
        <span style="color: #008000; font-weight: bold">except</span> <span style="color: #D2413A; font-weight: bold">IndexError</span>:
            <span style="color: #008000; font-weight: bold">pass</span>
        <span style="color: #008000">self</span><span style="color: #666666">.</span>_updateFontState( )
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">updateFontState</span>(<span style="color: #008000">self</span>):
        <span style="color: #408080; font-style: italic"># emit appropriate terminal control sequences if the state of</span>
        <span style="color: #408080; font-style: italic"># bold and/or italic(==underline) has just changed</span>
        <span style="color: #008000; font-weight: bold">try</span>:
            newState <span style="color: #666666">=</span> <span style="color: #008000">self</span><span style="color: #666666">.</span>fontStack[<span style="color: #666666">-1</span>]
        <span style="color: #008000; font-weight: bold">except</span> <span style="color: #D2413A; font-weight: bold">IndexError</span>:
            newState <span style="color: #666666">=</span> <span style="color: #008000">False</span>, <span style="color: #008000">False</span>
        <span style="color: #008000; font-weight: bold">if</span> <span style="color: #008000">self</span><span style="color: #666666">.</span>fontState <span style="color: #666666">!=</span> newState:
            <span style="color: #408080; font-style: italic"># relevant state change: reset terminal</span>
            <span style="color: #008000; font-weight: bold">print</span> perform_reset,
            <span style="color: #408080; font-style: italic"># set underine and/or bold if needed</span>
            <span style="color: #008000; font-weight: bold">if</span> newState[<span style="color: #666666">0</span>]:
                <span style="color: #008000; font-weight: bold">print</span> set_underline,
            <span style="color: #008000; font-weight: bold">if</span> newState[<span style="color: #666666">1</span>]:
                <span style="color: #008000; font-weight: bold">print</span> set_bold,
            <span style="color: #408080; font-style: italic"># remember the two flags as our current font-state</span>
            <span style="color: #008000">self</span><span style="color: #666666">.</span>fontState <span style="color: #666666">=</span> newState
<span style="color: #408080; font-style: italic"># make writer, formatter and parser objects, connecting them as needed</span>
myWriter <span style="color: #666666">=</span> formatter<span style="color: #666666">.</span>DumbWriter( )
<span style="color: #008000; font-weight: bold">if</span> sys<span style="color: #666666">.</span>stdout<span style="color: #666666">.</span>isatty( ):
    myFormatter <span style="color: #666666">=</span> TtyFormatter(myWriter)
<span style="color: #008000; font-weight: bold">else</span>:
    myFormatter <span style="color: #666666">=</span> formatter<span style="color: #666666">.</span>AbstractFormatter(myWriter)
myParser <span style="color: #666666">=</span> htmllib<span style="color: #666666">.</span>HTMLParser(myFormatter)
<span style="color: #408080; font-style: italic"># feed all of standard input to the parser, then terminate operations</span>
myParser<span style="color: #666666">.</span>feed(sys<span style="color: #666666">.</span>stdin<span style="color: #666666">.</span>read( ))
myParser<span style="color: #666666">.</span>close( )
</pre></div>
</div></div>
<div class="section" id="id3">
<h3>讨论</h3>
<p>Python标准库中的 <tt class="docutils literal"><span class="pre">formatter.AbstractFormatter</span></tt> 基本类可以工作在任何地方。而本配方中的 <tt class="docutils literal"><span class="pre">TtyFormatter</span></tt> 子类則依赖于类Unix的终端。确切的说是依赖于Unix命令 <tt class="docutils literal"><span class="pre">tput</span></tt> , 利用其获取控制符以输出粗体或下划线，并可以重置终端状态。</p>
<p>本配方中的方法要求只要系统中有 <tt class="docutils literal"><span class="pre">tput</span></tt> 命令即可工作，所以本配方可以工作于包括Linux，Mac OS X 在内的大多数类Unix系统。</p>
<p>如果你的终端模拟器支持其他控制输出样式的控制符，你可以对 <tt class="docutils literal"><span class="pre">TtyFormatter</span></tt> 做响应的调整。比如，在Windows系统上，cmd.exe 命令窗口支持标准ANSI控制符。你可以将这些控制符编入要运行的脚本中。</p>
<p>多数情况下，你可能倾向于使用诸如 <tt class="docutils literal"><span class="pre">lynx</span> <span class="pre">-dump</span> <span class="pre">-</span></tt> 这样的Unix命令，以获得比本配方更加丰富的输出格式。但是如果你正好面对一个没有 <tt class="docutils literal"><span class="pre">lynx</span></tt> 命令的系统，而该系统又恰好安装有Python，那么本配方的方法就很有用了。</p>
</div>
<div class="section" id="id4">
<h3>参见</h3>
<p>Python标准库参考手册和Python in a Nutshell 中关于 <tt class="docutils literal"><span class="pre">formatter</span></tt> 和 <tt class="docutils literal"><span class="pre">htmllib</span></tt> 模块的介绍；使用 <tt class="docutils literal"><span class="pre">man</span> <span class="pre">tput</span></tt> 来了解更多关于 <tt class="docutils literal"><span class="pre">tput</span></tt> 的信息。</p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;submitHeadline=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;title=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;title=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;title=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;bm_description=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;T=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;title=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;title=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC+@+http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fconverting-html-documents-to-text-on-a-unix-terminal&amp;t=Python%E9%A3%9F%E8%B0%B1-1.25.%E5%9C%A8Unix%E7%BB%88%E7%AB%AF%E4%B8%8A%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BAHTML%E6%96%87%E6%9C%AC" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/python/converting-html-documents-to-text-on-a-unix-terminal/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python食谱-1.24.使指定的字符串忽略大小写</title>
		<link>http://blog.shine-it.net/python/making-some-string-case-insensitive</link>
		<comments>http://blog.shine-it.net/python/making-some-string-case-insensitive#comments</comments>
		<pubDate>Tue, 15 Sep 2009 03:54:15 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[Python食谱]]></category>
		<category><![CDATA[str]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/python/making-some-string-case-insensitive</guid>
		<description><![CDATA[原文作者:Dale Strickland-Clark, Peter Cogolo, Mark McMahon 中文翻译:Tony (digitalsatori) 问题 如何才能使某些字符串在比较或查询时能忽略大小写，而在其它操作时能保持其原来的大小写？ 解决方法 最佳的方案就是把这样需求的字符串封装在一个如下例所示的字符串的子类中： class iStr(str): &#34;&#34;&#34; 忽略大小写字符串类。 除了在比较和搜索时忽略大小写，其它与str的表现完全一样， &#34;&#34;&#34; def _ _init_ _(self, *args): self._lowered = str.lower(self) def _ _repr_ _(self): return &#39;%s(%s)&#39; % (type(self)._ _name_ _, str._ _repr_ _(self)) def _ _hash_ _(self): return hash(self._lowered) def lower(self): return self._lowered def _make_case_insensitive(name): &#39;&#39;&#39; 将str中的一个方法改为忽略大小写后封装到iStr中。&#39;&#39;&#39; str_meth = [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">

<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">原文作者:</th><td class="field-body">Dale Strickland-Clark, Peter Cogolo, Mark McMahon</td>
</tr>
<tr class="field"><th class="docinfo-name">中文翻译:</th><td class="field-body">Tony (digitalsatori)</td>
</tr>
</tbody>
</table>
<!-- -*- mode: rst -*- -->
<div class="section" id="id1">
<h3>问题</h3>
<p>如何才能使某些字符串在比较或查询时能忽略大小写，而在其它操作时能保持其原来的大小写？</p>
</div>
<div class="section" id="id2">
<h3>解决方法</h3>
<p>最佳的方案就是把这样需求的字符串封装在一个如下例所示的字符串的子类中：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">class</span> <span style="color: #0000FF; font-weight: bold">iStr</span>(<span style="color: #008000">str</span>):
    <span style="color: #BA2121; font-style: italic">&quot;&quot;&quot;</span>
<span style="color: #BA2121; font-style: italic">    忽略大小写字符串类。</span>
<span style="color: #BA2121; font-style: italic">    除了在比较和搜索时忽略大小写，其它与str的表现完全一样，</span>
<span style="color: #BA2121; font-style: italic">    &quot;&quot;&quot;</span>
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_</span> _init_ _(<span style="color: #008000">self</span>, <span style="color: #666666">*</span>args):
        <span style="color: #008000">self</span><span style="color: #666666">.</span>_lowered <span style="color: #666666">=</span> <span style="color: #008000">str</span><span style="color: #666666">.</span>lower(<span style="color: #008000">self</span>)
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_</span> _repr_ _(<span style="color: #008000">self</span>):
        <span style="color: #008000; font-weight: bold">return</span> <span style="color: #BA2121">&#39;</span><span style="color: #BB6688; font-weight: bold">%s</span><span style="color: #BA2121">(</span><span style="color: #BB6688; font-weight: bold">%s</span><span style="color: #BA2121">)&#39;</span> <span style="color: #666666">%</span> (<span style="color: #008000">type</span>(<span style="color: #008000">self</span>)<span style="color: #666666">.</span>_ _name_ _, <span style="color: #008000">str</span><span style="color: #666666">.</span>_ _repr_ _(<span style="color: #008000">self</span>))
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_</span> _hash_ _(<span style="color: #008000">self</span>):
        <span style="color: #008000; font-weight: bold">return</span> <span style="color: #008000">hash</span>(<span style="color: #008000">self</span><span style="color: #666666">.</span>_lowered)
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">lower</span>(<span style="color: #008000">self</span>):
        <span style="color: #008000; font-weight: bold">return</span> <span style="color: #008000">self</span><span style="color: #666666">.</span>_lowered
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_make_case_insensitive</span>(name):
    <span style="color: #BA2121; font-style: italic">&#39;&#39;&#39; 将str中的一个方法改为忽略大小写后封装到iStr中。&#39;&#39;&#39;</span>
    str_meth <span style="color: #666666">=</span> <span style="color: #008000">getattr</span>(<span style="color: #008000">str</span>, name)
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">x</span>(<span style="color: #008000">self</span>, other, <span style="color: #666666">*</span>args):
        <span style="color: #BA2121; font-style: italic">&#39;&#39;&#39; 尝试将&#39;other&#39;转为小写。通常情况下others是字符串，</span>
<span style="color: #BA2121; font-style: italic">            但因为字符串可以跟其他非字符串作比较，</span>
<span style="color: #BA2121; font-style: italic">            所以可能有无法转为小写的形式而保持其原样。</span>
<span style="color: #BA2121; font-style: italic">        &#39;&#39;&#39;</span>
        <span style="color: #008000; font-weight: bold">try</span>: other <span style="color: #666666">=</span> other<span style="color: #666666">.</span>lower( )
        <span style="color: #008000; font-weight: bold">except</span> (<span style="color: #D2413A; font-weight: bold">TypeError</span>, <span style="color: #D2413A; font-weight: bold">AttributeError</span>, <span style="color: #D2413A; font-weight: bold">ValueError</span>): <span style="color: #008000; font-weight: bold">pass</span>
        <span style="color: #008000; font-weight: bold">return</span> str_meth(<span style="color: #008000">self</span><span style="color: #666666">.</span>_lowered, other, <span style="color: #666666">*</span>args)
    <span style="color: #408080; font-style: italic"># 对于Python2.4 以后的版本，可以添加以下语句： x.func_name = name</span>
    <span style="color: #008000">setattr</span>(iStr, name, x)
<span style="color: #408080; font-style: italic"># 对指定的方法调用  _make_case_insensitive 函数</span>
<span style="color: #008000; font-weight: bold">for</span> name <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #BA2121">&#39;eq lt le gt gt ne cmp contains&#39;</span><span style="color: #666666">.</span>split( ):
    _make_case_insensitive(<span style="color: #BA2121">&#39;_ _</span><span style="color: #BB6688; font-weight: bold">%s</span><span style="color: #BA2121">_ _&#39;</span> <span style="color: #666666">%</span> name)
<span style="color: #008000; font-weight: bold">for</span> name <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #BA2121">&#39;count endswith find index rfind rindex startswith&#39;</span><span style="color: #666666">.</span>split( ):
    _make_case_insensitive(name)
<span style="color: #408080; font-style: italic"># 这里注意我们没有修改的方法有 &#39;replace&#39;, &#39;split&#39;, &#39;strip&#39;, ...</span>
<span style="color: #408080; font-style: italic"># 当然如果你原意，完全可以将他们也添加进来</span>
<span style="color: #008000; font-weight: bold">del</span> _make_case_insensitive    <span style="color: #408080; font-style: italic"># 不再需要这个辅助函数了，删除之</span>
</pre></div>
</div></div>
<div class="section" id="id3">
<h3>讨论</h3>
<p>构建这个iStr类值得我们注意的是：首先，因为考虑到字符串的小写版本会在未来的使用中频繁的使用，我们在 <tt class="docutils literal"><span class="pre">__init__</span></tt> 方法中一次性创建了其小写版本。该小写版本的字符串保存在类的私有属性中，但不是&quot;强制私有&quot;（即，我们使用一个前置下划线而不是两个）。这是因为如果要创建iStr的子类（比如象解决方案方案中提到的那样创建一个子类扩展iStr目前没有涉及的忽略大小写的字符串分割，替换等功能），该子类可能需要访问到其父类的内部信息。iStr中没有提供诸如replace 等的&quot;忽略大小写&quot;版本的方法是因为这样做在一般情况下会让输入输出的关系变得混淆不清。因此，我们鼓励在特别的应用中，通过创建子类来扩展所需的动能。比方说，因为replace 没有被封装在 iStr 中，对iStr的实例调用replace方法，返回的是str实例，而非iStr实例。如果这会给程序带来问题，我们可以将iStr的返回字符串的方法进行封装，确保其返回的是iStr 的实例。为此你需要创建一个类似于&quot;解决方案&quot;中的辅助函数：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_make_return_iStr</span>(name):
    str_meth <span style="color: #666666">=</span> <span style="color: #008000">getattr</span>(<span style="color: #008000">str</span>, name)
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">x</span>(<span style="color: #666666">*</span>args):
        <span style="color: #008000; font-weight: bold">return</span> iStr(str_meth(<span style="color: #666666">*</span>args))
    <span style="color: #008000">setattr</span>(iStr, name, x)
</pre></div>
</div><p>然后你要对所有会返回字符串的相关字符串方法调用以上的辅助函数：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">for</span> name <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #BA2121">&#39;center ljust rjust strip lstrip rstrip&#39;</span><span style="color: #666666">.</span>split( ):
    _make_return_iStr(name)
</pre></div>
</div><p>字符串中有将近20个此这类方法（包括诸如 <tt class="docutils literal"><span class="pre">__add__</span></tt>, <tt class="docutils literal"><span class="pre">__mul__</span></tt> 等特殊方法），你还可以对比如 <tt class="docutils literal"><span class="pre">split</span></tt> 和 <tt class="docutils literal"><span class="pre">join</span></tt> 进行类似的封装，但要做一些特殊处理。而对于 <tt class="docutils literal"><span class="pre">encode</span></tt> <tt class="docutils literal"><span class="pre">decode</span></tt> 这样的方法就无法这样封装了，除非我们也设计了忽略大小写的unicode子类。在实际应用中，这些方法都被证实运行正常可靠。通过本例可见Python字符串对象的丰富功能使全局性的自定义工作颇费功夫。</p>
<p>iStr的构筑中我们尽力避免使用繁复的代码（重复而容易出错的代码）来重构字符串中的每个方法。自定义的 metaclass 或者其它的高级技术在本例中也不适用。我们创建了一个辅助函数并以此创建并安装clousre封装函数， 然后通过两个循环来调用该函数，一个循环服务于普通方法，另一个服务于特殊方法。该循环要置于类定义之后，因为它们是用来修改iStr类对象的，必须在创建了类对象之后
才能对其修改。</p>
<p>Python2.4及以上的版本可以为函数对象的 <tt class="docutils literal"><span class="pre">func_name</span></tt> 重新赋值，这样做可以在对 <tt class="docutils literal"><span class="pre">iStr</span></tt> 实施自省操作（比如在互动python解释器中使用help函数）得到一个清晰无误的结果。但是Python2.3将函数对象中的 <tt class="docutils literal"><span class="pre">func_name</span></tt> 属性视为只读，因此在本配方中只是在备注中提到了这种用法，而没有实际的实施以避免对Python2.3不兼容。</p>
<p>在操作中忽略大小写（但是保留原来的大小写形式）的字符串有很多的用途。比如，可以提供更加通融的用户输入，用于诸如windows或Macintosh的忽略大小写的文件系统的的文件名匹配。我们可能需要创建各种各样的&quot;忽略大小写&quot;的容器类，比如字典，列表，集合等等使容器成员或字符串键能忽略大小写。一个比较好的方法是一次性定义好&quot;忽略大小写&quot;的比较和搜索功能。在创建&quot;忽略大小写容器类&quot;时，或改变容器成员时，我们可以利用本配方中的 <tt class="docutils literal"><span class="pre">iStr</span></tt> 将其中的 <tt class="docutils literal"><span class="pre">str</span></tt> 转变为 <tt class="docutils literal"><span class="pre">iStr</span></tt> 实例。</p>
<p>比如，对于一个其成员都为字符串的列表，希望能按照忽略大小写的方式来处理（比如在使用 <tt class="docutils literal"><span class="pre">sort</span></tt> <tt class="docutils literal"><span class="pre">count</span></tt> <tt class="docutils literal"><span class="pre">index</span></tt> 等方法时）：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">class</span> <span style="color: #0000FF; font-weight: bold">iList</span>(<span style="color: #008000">list</span>):

    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_</span> _init_ _(<span style="color: #008000">self</span>, <span style="color: #666666">*</span>args):
        <span style="color: #008000">list</span><span style="color: #666666">.</span>_ _init_ _(<span style="color: #008000">self</span>, <span style="color: #666666">*</span>args)
        <span style="color: #408080; font-style: italic"># rely on _ _setitem_ _ to wrap each item into iStr...</span>
        <span style="color: #008000">self</span>[:] <span style="color: #666666">=</span> <span style="color: #008000">self</span>
    wrap_each_item <span style="color: #666666">=</span> iStr
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">_</span> _setitem_ _(<span style="color: #008000">self</span>, i, v):
        <span style="color: #008000; font-weight: bold">if</span> <span style="color: #008000">isinstance</span>(i, <span style="color: #008000">slice</span>): v <span style="color: #666666">=</span> <span style="color: #008000">map</span>(<span style="color: #008000">self</span><span style="color: #666666">.</span>wrap_each_item, v)
        <span style="color: #008000; font-weight: bold">else</span>: v <span style="color: #666666">=</span> <span style="color: #008000">self</span><span style="color: #666666">.</span>wrap_each_item(v)
        <span style="color: #008000">list</span><span style="color: #666666">.</span>_ _setitem_ _(<span style="color: #008000">self</span>, i, v)
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">append</span>(<span style="color: #008000">self</span>, item):
        <span style="color: #008000">list</span><span style="color: #666666">.</span>append(<span style="color: #008000">self</span>, <span style="color: #008000">self</span><span style="color: #666666">.</span>wrap_each_item(item))
    <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">extend</span>(<span style="color: #008000">self</span>, seq):
        <span style="color: #008000">list</span><span style="color: #666666">.</span>extend(<span style="color: #008000">self</span>, <span style="color: #008000">map</span>(<span style="color: #008000">self</span><span style="color: #666666">.</span>wrap_each_item, seq))
</pre></div>
</div><p>如果你希望在特定的程序中对上例使用自定义的 <tt class="docutils literal"><span class="pre">iStr</span></tt> 的子类，只需要继承 <tt class="docutils literal"><span class="pre">iList</span></tt>  并覆写一个类成员 <tt class="docutils literal"><span class="pre">wrapped_each_item</span></tt></p>
</div>
<div class="section" id="id4">
<h3>参考</h3>
<p>Python库参考手册和Python in a Nutshell 中关于 <tt class="docutils literal"><span class="pre">str</span></tt>, 字符串方法的章节，以及关于用于比较和hashing的特殊方法的说明。</p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;submitHeadline=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;title=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;title=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;title=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;bm_description=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;T=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;title=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;title=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99+@+http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fmaking-some-string-case-insensitive&amp;t=Python%E9%A3%9F%E8%B0%B1-1.24.%E4%BD%BF%E6%8C%87%E5%AE%9A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/python/making-some-string-case-insensitive/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python食谱-1.23.Unicode数据编码输出到XML或HTML文件</title>
		<link>http://blog.shine-it.net/python/encoding-unicode-data-for-xml-and-html</link>
		<comments>http://blog.shine-it.net/python/encoding-unicode-data-for-xml-and-html#comments</comments>
		<pubDate>Thu, 10 Sep 2009 09:32:29 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[codecs]]></category>
		<category><![CDATA[htmlentitydefs]]></category>
		<category><![CDATA[Python食谱]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[xmlcharrefreplace]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/python/encoding-unicode-data-for-xml-and-html</guid>
		<description><![CDATA[原文作者:David Goodger, Peter Cogolo 中文翻译:Tony (digitalsatori) 问题 要将Uicode文本输出到HTML或是XML应用程序，且只能用较为流行但受限的编码比如：ASCII码，或Latin-1，如何操作？ 解决方法 Python 有一个叫 xmlcharrefreplace 的编码出错处理器，它可以将选定编码之外的字符替换为XML数字字符参考(XML numeric characters references）： def encode_for_xml(unicode_data, encoding=&#39;ascii&#39;): return unicode_data.encode(encoding, &#39;xmlcharrefreplace&#39;) 上述的方法也可以用来处理HTML输出，但是我们希望能用HTML的‘符号实体‘(symbolic entity)。这样的话，我们就要自己定义一个函数并将其注册为编码错误处理函数。弄这么个函数其实并不难，因为Python标准库中已经有一个叫 htmlentitydefs 的模块，其包含了所有的HTML的实体定义。 import codecs from htmlentitydefs import codepoint2name def html_replace(exc): if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)): s = [ u&#39;&#38;%s;&#39; % codepoint2name[ord(c)] for c in exc.object[exc.start:exc.end] ] return &#39;&#39;.join(s), exc.end else: raise TypeError(&#34;can&#39;t [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">

<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">原文作者:</th><td class="field-body">David Goodger, Peter Cogolo</td>
</tr>
<tr class="field"><th class="docinfo-name">中文翻译:</th><td class="field-body">Tony (digitalsatori)</td>
</tr>
</tbody>
</table>
<!-- -*- mode: rst -*- -->
<div class="section" id="id1">
<h3>问题</h3>
<p>要将Uicode文本输出到HTML或是XML应用程序，且只能用较为流行但受限的编码比如：ASCII码，或Latin-1，如何操作？</p>
</div>
<div class="section" id="id2">
<h3>解决方法</h3>
<p>Python 有一个叫 <tt class="docutils literal"><span class="pre">xmlcharrefreplace</span></tt> 的编码出错处理器，它可以将选定编码之外的字符替换为XML数字字符参考(XML numeric characters references）：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">encode_for_xml</span>(unicode_data, encoding<span style="color: #666666">=</span><span style="color: #BA2121">&#39;ascii&#39;</span>):
    <span style="color: #008000; font-weight: bold">return</span> unicode_data<span style="color: #666666">.</span>encode(encoding, <span style="color: #BA2121">&#39;xmlcharrefreplace&#39;</span>)
</pre></div>
</div><p>上述的方法也可以用来处理HTML输出，但是我们希望能用HTML的‘符号实体‘(symbolic entity)。这样的话，我们就要自己定义一个函数并将其注册为编码错误处理函数。弄这么个函数其实并不难，因为Python标准库中已经有一个叫 <tt class="docutils literal"><span class="pre">htmlentitydefs</span></tt> 的模块，其包含了所有的HTML的实体定义。</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">codecs</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">htmlentitydefs</span> <span style="color: #008000; font-weight: bold">import</span> codepoint2name
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">html_replace</span>(exc):
    <span style="color: #008000; font-weight: bold">if</span> <span style="color: #008000">isinstance</span>(exc, (<span style="color: #D2413A; font-weight: bold">UnicodeEncodeError</span>, <span style="color: #D2413A; font-weight: bold">UnicodeTranslateError</span>)):
        s <span style="color: #666666">=</span> [ <span style="color: #BA2121">u&#39;&amp;</span><span style="color: #BB6688; font-weight: bold">%s</span><span style="color: #BA2121">;&#39;</span> <span style="color: #666666">%</span> codepoint2name[<span style="color: #008000">ord</span>(c)]
              <span style="color: #008000; font-weight: bold">for</span> c <span style="color: #AA22FF; font-weight: bold">in</span> exc<span style="color: #666666">.</span>object[exc<span style="color: #666666">.</span>start:exc<span style="color: #666666">.</span>end] ]
        <span style="color: #008000; font-weight: bold">return</span> <span style="color: #BA2121">&#39;&#39;</span><span style="color: #666666">.</span>join(s), exc<span style="color: #666666">.</span>end
    <span style="color: #008000; font-weight: bold">else</span>:
        <span style="color: #008000; font-weight: bold">raise</span> <span style="color: #D2413A; font-weight: bold">TypeError</span>(<span style="color: #BA2121">&quot;can&#39;t handle </span><span style="color: #BB6688; font-weight: bold">%s</span><span style="color: #BA2121">&quot;</span> <span style="color: #666666">%</span> exc<span style="color: #666666">.</span>_ _name_ _)
codecs<span style="color: #666666">.</span>register_error(<span style="color: #BA2121">&#39;html_replace&#39;</span>, html_replace)
</pre></div>
</div><p>这个错误处理函数注册好之后，我们可以用一个函数来将它封装起来：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">encode_for_html</span>(unicode_data, encoding<span style="color: #666666">=</span><span style="color: #BA2121">&#39;ascii&#39;</span>):
    <span style="color: #008000; font-weight: bold">return</span> unicode_data<span style="color: #666666">.</span>encode(encoding, <span style="color: #BA2121">&#39;html_replace&#39;</span>)
</pre></div>
</div></div>
<div class="section" id="id3">
<h3>讨论</h3>
<p>现在用下面的代码来测试一下(将之与上面的函数放在同一个Python文件中)：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">if</span> _ _name_ _ <span style="color: #666666">==</span> <span style="color: #BA2121">&#39;_ _main_ _&#39;</span>:
    <span style="color: #408080; font-style: italic"># demo</span>
    data <span style="color: #666666">=</span> <span style="color: #BA2121">u&#39;&#39;&#39;</span><span style="color: #BB6622; font-weight: bold">\</span>
<span style="color: #BA2121">&lt;html&gt;</span>
<span style="color: #BA2121">&lt;head&gt;</span>

<span style="color: #BA2121">&lt;/head&gt;</span>
<span style="color: #BA2121">&lt;body&gt;</span>
<span style="color: #BA2121">&lt;p&gt;accented characters:</span>
<span style="color: #BA2121">&lt;ul&gt;</span>
<span style="color: #BA2121">&lt;li&gt;</span><span style="color: #BB6622; font-weight: bold">\xe0</span><span style="color: #BA2121"> (a + grave)</span>
<span style="color: #BA2121">&lt;li&gt;</span><span style="color: #BB6622; font-weight: bold">\xe7</span><span style="color: #BA2121"> (c + cedilla)</span>
<span style="color: #BA2121">&lt;li&gt;</span><span style="color: #BB6622; font-weight: bold">\xe9</span><span style="color: #BA2121"> (e + acute)</span>
<span style="color: #BA2121">&lt;/ul&gt;</span>
<span style="color: #BA2121">&lt;p&gt;symbols:</span>
<span style="color: #BA2121">&lt;ul&gt;</span>
<span style="color: #BA2121">&lt;li&gt;</span><span style="color: #BB6622; font-weight: bold">\xa3</span><span style="color: #BA2121"> (British pound)</span>
<span style="color: #BA2121">&lt;li&gt;</span><span style="color: #BB6622; font-weight: bold">\u20ac</span><span style="color: #BA2121"> (Euro)</span>
<span style="color: #BA2121">&lt;li&gt;</span><span style="color: #BB6622; font-weight: bold">\u221e</span><span style="color: #BA2121"> (infinity)</span>
<span style="color: #BA2121">&lt;/ul&gt;</span>
<span style="color: #BA2121">&lt;/body&gt;&lt;/html&gt;</span>
<span style="color: #BA2121">&#39;&#39;&#39;</span>
    <span style="color: #008000; font-weight: bold">print</span> encode_for_xml(data)
    <span style="color: #008000; font-weight: bold">print</span> encode_for_html(data)
</pre></div>
</div><p>运行这个文件，可以看到如下结果:</p>
<pre class="literal-block">
&lt;li&gt;&amp;#224; (a + grave)
&lt;li&gt;&amp;#231; (c + cedilla)
&lt;li&gt;&amp;#233; (e + acute)
   ...
&lt;li&gt;&amp;#163; (British pound)
&lt;li&gt;&amp;#8364; (Euro)
&lt;li&gt;&amp;#8734; (infinity)
   ...
&lt;li&gt;&amp;agrave; (a + grave)
&lt;li&gt;&amp;ccedil; (c + cedilla)
&lt;li&gt;&amp;eacute; (e + acute)
   ...
&lt;li&gt;&amp;pound; (British pound)
&lt;li&gt;&amp;euro; (Euro)
&lt;li&gt;&amp;infin; (infinity)
</pre>
<p><tt class="docutils literal"><span class="pre">encode_for_xml</span></tt> 比较通用， <tt class="docutils literal"><span class="pre">encode_for_html</span></tt> 产生的结果的可读性较强。两个函数产生的结果放到浏览器里看是完全一样的。你可以运行以上这个Python文件并将结果重定向到一个html文件，然后用浏览器打开查看。</p>
<p>必须要记得Unicode数据在打印或写入文件前一定要做编码处理。UTF-8是一个不错的字符编码，因为他能处理所有的Unicode字符。但是目前还有很多用户和程序在使用ASCII码或Latin-1。如果Unicode数据中有超出指定编码范围的字符（比如本例中的带重音的字符和所有的符号都无法用ASCII编码，而无限符号(infinity)无法用Latin-1编码），指定的编码无法自己处理这些数据。Python提供了一个称为 <tt class="docutils literal"><span class="pre">xmlcharrefreplace</span></tt> 错误处理函数，它可以将无法编码的字符用XML数字字符参考来替代，比如： <tt class="docutils literal"><span class="pre">&amp;#8734;</span></tt> 表示无限符号。在本配方中展示了如何来编写和注册另一个近似的错误处理函数 <tt class="docutils literal"><span class="pre">html_replace</span></tt> ，这个函数主要用于处理HTML输出。 <tt class="docutils literal"><span class="pre">html_replace</span></tt> 将无法编码的字符用更加可读的HTML符号实体来替代，比如用 <tt class="docutils literal"><span class="pre">&amp;infin;</span></tt> 来表示无限符号。 <tt class="docutils literal"><span class="pre">html_replace</span></tt> 不是很通用，因为它并不能处理所有的Unicode字符，而且也不能用于非HTML的应用环境。</p>
<p>上述的错误处理函数对于除XML或HTML以外的输出是没有意义的。比如TeX或其它标记语言并不能识别XML数字字符参考。当然，如果你知道如何为这些标记语言创建相应的符号参考，你就可以用本配方中的方法来创建和注册相应的错误处理函数。</p>
<p>另外，Python标准库中的 <tt class="docutils literal"><span class="pre">codecs</span></tt> 模块提供了一个有效的方法，将Unicode数据编码输出到文件，并根据设定进行错误处理：</p>
<div class="codeblock"><div class="highlight"><pre>outfile <span style="color: #666666">=</span> codecs<span style="color: #666666">.</span>open(<span style="color: #BA2121">&#39;out.html&#39;</span>, mode<span style="color: #666666">=</span><span style="color: #BA2121">&#39;w&#39;</span>, encoding<span style="color: #666666">=</span><span style="color: #BA2121">&#39;ascii&#39;</span>,
                       errors<span style="color: #666666">=</span><span style="color: #BA2121">&#39;html_replace&#39;</span>)
</pre></div>
</div><p>现在我们可以用 <tt class="docutils literal"><span class="pre">outfile.write(unicode_data)</span></tt> 将任意Unicode字符串 <tt class="docutils literal"><span class="pre">unicode_data</span></tt> 输出到指定的文件，编码和错误处理会自动进行。当输出结束后，我们需要调用 <tt class="docutils literal"><span class="pre">outfile.close()</span></tt> 。</p>
</div>
<div class="section" id="id4">
<h3>参见</h3>
<p>Python库参考手册和Python in a Nutshelll中关于 <tt class="docutils literal"><span class="pre">codecs</span></tt> 模块和 <tt class="docutils literal"><span class="pre">htmlentitydefs</span></tt> 的介绍</p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;submitHeadline=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;title=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;title=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;title=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;bm_description=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;T=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;title=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;title=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6+@+http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fencoding-unicode-data-for-xml-and-html&amp;t=Python%E9%A3%9F%E8%B0%B1-1.23.Unicode%E6%95%B0%E6%8D%AE%E7%BC%96%E7%A0%81%E8%BE%93%E5%87%BA%E5%88%B0XML%E6%88%96HTML%E6%96%87%E4%BB%B6" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/python/encoding-unicode-data-for-xml-and-html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python食谱-1.22.将Unicode字符打印到标准输出</title>
		<link>http://blog.shine-it.net/python/printing-unicode-characters-to-standard-output</link>
		<comments>http://blog.shine-it.net/python/printing-unicode-characters-to-standard-output#comments</comments>
		<pubDate>Tue, 08 Sep 2009 02:28:36 +0000</pubDate>
		<dc:creator>digitalsatori</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Python食谱]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://blog.shine-it.net/python/printing-unicode-characters-to-standard-output</guid>
		<description><![CDATA[原文作者:David Ascher 中文翻译:Tony (digitalsatori) 问题 需要将Unicode字符打印到标准输出（比如在Debug时），但是它们不能使用默认的编码，怎么办？ 解决方法 使用Python标准库中的 codecs 模块作为编码转换器来封装 sys.stdout (标准输出流）。比如我们的输出是到一个使用ISO-8859-1编码的终端，可以这样来写代码： import codecs, sys sys.stdout = codecs.lookup(&#39;iso8859-1&#39;)[-1](sys.stdout) 讨论 Unicode字符串处在一个足以容纳全世界所有语言所包含的字符的空间中。幸运的是，作为Unicode的使用者，我们不必了解Unicode字符串的内部表现方式。但是对于象 sys.stdout 这样的文件流，只能处理与特定编码关联的字节。我们可以改变Python的 site 模块来改变文件所使用的默认编码，但是这样的改变会全局影响Python ，使其它使用Python安装时的默认编码的程序出现混乱。（Python的默认标准编码是ASCII）。因此，我们不推荐这类改动。 本配方采用了一个更好的方法：将 sys.stdout 重新绑定到一个接收Unicode输入，以ISO-8859-1（也称为&#34;Latin-1&#34;）编码输出的文件流。该方法并不会改变之前的 sys.stdout 的编码。首先我们保存当前的以ASCII为编码的 sys.stdout: &#62;&#62;&#62; old = sys.stdout 然后，我们创建一个无法通过 sys.stdout 直接输出的Unicode字符串： &#62;&#62;&#62; char = u&#34;\N{LATIN SMALL LETTER A WITH DIAERESIS}&#34; &#62;&#62;&#62; print char Traceback (most recent call last): [...]]]></description>
			<content:encoded><![CDATA[
<div class="document">

<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">原文作者:</th><td class="field-body">David Ascher</td>
</tr>
<tr class="field"><th class="docinfo-name">中文翻译:</th><td class="field-body">Tony (digitalsatori)</td>
</tr>
</tbody>
</table>
<!-- -*- mode: rst -*- -->
<div class="section" id="id1">
<h3>问题</h3>
<p>需要将Unicode字符打印到标准输出（比如在Debug时），但是它们不能使用默认的编码，怎么办？</p>
</div>
<div class="section" id="id2">
<h3>解决方法</h3>
<p>使用Python标准库中的 <tt class="docutils literal"><span class="pre">codecs</span></tt> 模块作为编码转换器来封装 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> (标准输出流）。比如我们的输出是到一个使用ISO-8859-1编码的终端，可以这样来写代码：</p>
<div class="codeblock"><div class="highlight"><pre><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">codecs</span><span style="color: #666666">,</span> <span style="color: #0000FF; font-weight: bold">sys</span>
sys<span style="color: #666666">.</span>stdout <span style="color: #666666">=</span> codecs<span style="color: #666666">.</span>lookup(<span style="color: #BA2121">&#39;iso8859-1&#39;</span>)[<span style="color: #666666">-1</span>](sys<span style="color: #666666">.</span>stdout)
</pre></div>
</div></div>
<div class="section" id="id3">
<h3>讨论</h3>
<p>Unicode字符串处在一个足以容纳全世界所有语言所包含的字符的空间中。幸运的是，作为Unicode的使用者，我们不必了解Unicode字符串的内部表现方式。但是对于象 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> 这样的文件流，只能处理与特定编码关联的字节。我们可以改变Python的 <tt class="docutils literal"><span class="pre">site</span></tt> 模块来改变文件所使用的默认编码，但是这样的改变会全局影响Python ，使其它使用Python安装时的默认编码的程序出现混乱。（Python的默认标准编码是ASCII）。因此，我们不推荐这类改动。</p>
<p>本配方采用了一个更好的方法：将 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> 重新绑定到一个接收Unicode输入，以ISO-8859-1（也称为&quot;Latin-1&quot;）编码输出的文件流。该方法并不会改变之前的 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> 的编码。首先我们保存当前的以ASCII为编码的 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt>:</p>
<pre class="doctest-block">
&gt;&gt;&gt; old = sys.stdout
</pre>
<p>然后，我们创建一个无法通过 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> 直接输出的Unicode字符串：</p>
<pre class="doctest-block">
&gt;&gt;&gt; char = u&quot;\N{LATIN SMALL LETTER A WITH DIAERESIS}&quot;
&gt;&gt;&gt; print char
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in ?
UnicodeError: ASCII encoding error: ordinal not in range(128)
</pre>
<p>如果在做以上操作时没有出现错误，那是因为Python认为它知道你的终端所使用的编码（比如你的终端是Python自带的开发环境IDLE, 多数情况下Python会使用正确的编码）。但是如果确实有错误信息出现，或者没有出现错误信息，但是输出并不是期待中的输出，因为Python并不知道你的终端使用的是比如UTF-8这种编码。我们可以将 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> 用以UTF-8编码的 <tt class="docutils literal"><span class="pre">codecs</span></tt> 输出流封装，并将 <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> 重新绑定到这个封装的输出流:</p>
<pre class="doctest-block">
&gt;&gt;&gt; sys.stdout = codecs.lookup('utf-8')[-1](sys.stdout)
&gt;&gt;&gt; print char
ä
</pre>
<p>以上方法工作的前提是，运行Python互动解释器的终端，终端模拟器，或其它窗口支持UTF-8编码，并且拥有需要显示的字符的字体。如果你没有符合这样要求的程序或设备，请在互联网上下载适用于你所使用平台的程序。</p>
</div>
<div class="section" id="id4">
<h3>参见</h3>
<p>在Python库参考手册和Python in a Nutshell中关于 <tt class="docutils literal"><span class="pre">codecs</span></tt> 和 <tt class="docutils literal"><span class="pre">site</span></tt> 模块，以及 <tt class="docutils literal"><span class="pre">sys</span></tt> 模块中的 <tt class="docutils literal"><span class="pre">setdefaultencoding</span></tt> 函数； <a class="reference external" href="http://blog.shine-it.net/python/handling-international-text-with-unicode">Python食谱1.20</a> <a class="reference external" href="http://blog.shine-it.net/python/converting-between-unicode-and-plain-string">Python食谱1.21</a></p>
</div>
</div>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>网络书签</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://buzz.yahoo.com/submit?submitUrl=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;submitHeadline=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA&amp;submitSummary=" rel="nofollow" title="添加书签至&nbsp;Buzz"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/buzz.png" title="添加书签至&nbsp;Buzz" alt="添加书签至&nbsp;Buzz" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;title=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;Del.icio.us"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="添加书签至&nbsp;Del.icio.us" alt="添加书签至&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;title=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;digg"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/digg.png" title="添加书签至&nbsp;digg" alt="添加书签至&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output" rel="nofollow" title="添加书签至&nbsp;Facebook"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="添加书签至&nbsp;Facebook" alt="添加书签至&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;title=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;Google Bookmarks"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/google.png" title="添加书签至&nbsp;Google Bookmarks" alt="添加书签至&nbsp;Google Bookmarks" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.mister-wong.com/index.php?action=addurl&amp;bm_url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;bm_description=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;Mister Wong"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/misterwong.png" title="添加书签至&nbsp;Mister Wong" alt="添加书签至&nbsp;Mister Wong" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.netscape.com/submit/?U=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;T=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;Netscape"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/netscape.png" title="添加书签至&nbsp;Netscape" alt="添加书签至&nbsp;Netscape" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;title=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;reddit"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="添加书签至&nbsp;reddit" alt="添加书签至&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;title=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;Stumble Upon"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="添加书签至&nbsp;Stumble Upon" alt="添加书签至&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output" rel="nofollow" title="添加书签至&nbsp;Technorati"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="添加书签至&nbsp;Technorati" alt="添加书签至&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://tipd.com/submit.php?url=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output" rel="nofollow" title="添加书签至&nbsp;Tip'd"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/tipd.png" title="添加书签至&nbsp;Tip'd" alt="添加书签至&nbsp;Tip'd" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA+@+http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output" rel="nofollow" title="添加书签至&nbsp;Twitter"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="添加书签至&nbsp;Twitter" alt="添加书签至&nbsp;Twitter" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://myweb2.search.yahoo.com/myresults/bookmarklet?u=http%3A%2F%2Fblog.shine-it.net%2Fpython%2Fprinting-unicode-characters-to-standard-output&amp;t=Python%E9%A3%9F%E8%B0%B1-1.22.%E5%B0%86Unicode%E5%AD%97%E7%AC%A6%E6%89%93%E5%8D%B0%E5%88%B0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA" rel="nofollow" title="添加书签至&nbsp;Yahoo My Web"><img class="social_img" src="http://blog.shine-it.net/wp-content/plugins/social-bookmarks/images/yahoo.png" title="添加书签至&nbsp;Yahoo My Web" alt="添加书签至&nbsp;Yahoo My Web" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://blog.shine-it.net/python/printing-unicode-characters-to-standard-output/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

