<?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>可可熊的窝 &#187; Python</title>
	<atom:link href="http://cocobear.info/blog/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://cocobear.info/blog</link>
	<description>K.I.S.S</description>
	<lastBuildDate>Tue, 17 Aug 2010 10:26:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>最近PyFetion不能登录-已更新</title>
		<link>http://cocobear.info/blog/2010/08/03/update-pyfetion/</link>
		<comments>http://cocobear.info/blog/2010/08/03/update-pyfetion/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 03:18:29 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[编程相关]]></category>
		<category><![CDATA[PyFetion]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=842</guid>
		<description><![CDATA[tanjelly同学更新了PyFetion，原因是移动对认证方式的一些小的变化，并不是以前的协议完全不可以用了。具体的细节可以参考上面的连接。 google code的Issue怎么没有邮件通知呢？还是别人发邮件我才知道的:-(]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/p/pytool/issues/detail?id=18">tanjelly</a>同学更新了<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>，原因是移动对认证方式的一些小的变化，并不是以前的协议完全不可以用了。具体的细节可以参考上面的连接。</p>
<p>google code的Issue怎么没有邮件通知呢？还是别人发邮件我才知道的:-(</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2010/08/03/update-pyfetion/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>更新百度搜藏导出工具</title>
		<link>http://cocobear.info/blog/2009/12/15/update-cang2html/</link>
		<comments>http://cocobear.info/blog/2009/12/15/update-cang2html/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 14:35:26 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[PyFetion]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/2009/12/15/%e6%9b%b4%e6%96%b0%e7%99%be%e5%ba%a6%e6%90%9c%e8%97%8f%e5%af%bc%e5%87%ba%e5%b7%a5%e5%85%b7/</guid>
		<description><![CDATA[可以支持分类(或者叫标签)的导出了。 PyFetion在google code页面加了一个下载连接，方便没有svn时直接下载代码;使用的是r49的版本 这似乎是一篇微博&#8230;]]></description>
			<content:encoded><![CDATA[<p>可以支持分类(或者叫标签)的导出了。<br />
<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>在google code页面加了一个下载连接，方便没有svn时直接下载代码;使用的是r49的版本</p>
<p>这似乎是一篇微博&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/12/15/update-cang2html/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>GAE上使用PyFetion做一个应用</title>
		<link>http://cocobear.info/blog/2009/12/15/app-use-pyfetion-on-gae/</link>
		<comments>http://cocobear.info/blog/2009/12/15/app-use-pyfetion-on-gae/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 06:22:14 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[编程相关]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[PyFetion]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=759</guid>
		<description><![CDATA[GAE上有一个cron jobs的功能，类似于Linux下的crontab，可以实现在指定规则的时间里去运行程序。利用这个功能和飞信的短信功能就完成一些简单的小应用，比如天气预报，服务器监控，股票大盘实时行情提醒等等。 拿服务器监控来说，我们先注册一个GAE账户，然后创建一个Application，下载一份GAE 的SDK，接下来就写代码了。 (以上过程请自行google之) monitor.py: PYTHON: #!/usr/bin/env python # -*- coding: utf-8 -*- #MIT License #By : cocobear.cn@gmail.com # &#160; from google.appengine.api import urlfetch from PyFetion import * &#160; def get&#40;&#41;: &#160; &#160; print&#40;'&#60;html&#62;&#60;body&#62;'&#41; &#160; &#160; url = 'http://61.236.244.162' &#160; &#160; result = urlfetch.fetch&#40;url&#41; &#160; &#160; if result.status_code == 200: &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上有一个cron jobs的功能，类似于Linux下的crontab，可以实现在指定规则的时间里去运行程序。利用这个功能和飞信的短信功能就完成一些简单的小应用，比如天气预报，服务器监控，股票大盘实时行情提醒等等。</p>
<p>拿服务器监控来说，我们先注册一个<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>账户，然后创建一个Application，下载一份<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a> 的SDK，接下来就写代码了。<br />
(以上过程请自行google之)</p>
<p>monitor.py:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-6">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#!/usr/bin/env <a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">python</a></span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># -*- coding: utf-8 -*-</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#MIT License</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#By : cocobear.cn@gmail.com</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">from</span> google.<span style="color: white;">appengine</span>.<span style="color: white;">api</span> <span style="color: #0088ff;font-weight:bold;">import</span> urlfetch</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">from</span> <a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a> <span style="color: #0088ff;font-weight:bold;">import</span> <span style="color: #993399;">*</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">def</span> get<span style="color: white;">&#40;</span><span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">print</span><span style="color: white;">&#40;</span><span style="color: #b7c274;">'&lt;html&gt;&lt;body&gt;'</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; url = <span style="color: #b7c274;">'http://61.236.244.162'</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; result = urlfetch.<span style="color: white;">fetch</span><span style="color: white;">&#40;</span>url<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">if</span> result.<span style="color: white;">status_code</span> == <span style="color: #00baff;color:#800000;">200</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">print</span><span style="color: white;">&#40;</span><span style="color: #b7c274;">'OK'</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">else</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; fetion = <a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a><span style="color: white;">&#40;</span><span style="color: #b7c274;">'136xxxx'</span>,<span style="color: #b7c274;">'123456'</span>,<span style="color: #b7c274;">'HTTP'</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; i = <span style="color: #00baff;color:#800000;">0</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">while</span> <span style="color: #ff7fff;">True</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">try</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fetion.<span style="color: white;">login</span><span style="color: white;">&#40;</span>FetionOnline<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fetion.<span style="color: white;">send_sms</span><span style="color: white;">&#40;</span><span style="color: #b7c274;">'服务器掉了!'</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fetion.<span style="color: white;">logout</span><span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">except</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">if</span> i<span style="color: #993399;">&gt;</span> <span style="color: #00baff;color:#800000;">5</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">break</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">continue</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">print</span><span style="color: white;">&#40;</span><span style="color: #b7c274;">'&lt;/body&gt;&lt;/html&gt;'</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">if</span> __name__ == <span style="color: #b7c274;">'__main__'</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; get<span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>很简单的代码，使用<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>的函数urlfetch.fetch来访问这个地址，如果失败调用<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>来发短信给自己做通知。</p>
<p>app.yaml:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-7">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">application: pythoning</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">version: <span style="color: #00baff;color:#800000;">1</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">runtime: <a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">python</a></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">api_version: <span style="color: #00baff;color:#800000;">1</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">handlers:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">- url: /console/.<span style="color: #993399;">*</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; script: $PYTHON_LIB/google/appengine/ext/admin</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; login: admin</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">- url: /monitor</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; script: monitor.<span style="color: white;">py</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">- url: /</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; static_files: index.<span style="color: white;">html</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; upload: index.<span style="color: white;">html</span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>这里指定url映射的规则，访问pythoning.appspot.com/monitor就会执行monitor.py脚本。application需要填写你申请<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>应用时的名称，也就是这个二级域名pythoning，version：当前代码的版本。</p>
<p>index.html:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-8">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">首页你可以做别的事，比如放个人主页，然后把自己域名指过来。</div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>cron.yaml:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-9">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">cron:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">- description: watch http server </div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; url: /monitor</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; schedule: every <span style="color: #00baff;color:#800000;">1</span> minutes</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; timezone: Asia/Shanghai</div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>关键的一个文件，对monitor这个url进行定时执行，这里是每分钟执行一次; 如果你是写天气预报，就可以写为 7:00 every day，每天早上7点发一次天气预报。</p>
<p>写完这些以后，运行命令:<br />
ls demos/test<br />
app.yaml cron.yaml index.html monitor.py <a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>.py<br />
<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">python</a> appcfg.py update demos/test<br />
把你的代码提交到<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>服务器上，你可以在<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>的后台Cron Jobs看到：</p>
<blockquote><p>/monitor<br />
watch http server	 every 1 minutes (Asia/Shanghai)<br />
2009/12/15 14:06:50 on time Success
</p></blockquote>
<p>在<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上使用r49版本的<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>，请注释掉from select import select,如果只是像上面做提醒的话最后去掉下面的代码(824行):</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-10">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #ff7fff;">self</span>.<span style="color: white;">get_personal_info</span><span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">if</span> <span style="color: #0088ff;font-weight:bold;">not</span> <span style="color: #ff7fff;">self</span>.<span style="color: white;">get_contactlist</span><span style="color: white;">&#40;</span><span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; d_print<span style="color: white;">&#40;</span><span style="color: #b7c274;">&quot;get contactlist error&quot;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> <span style="color: #ff7fff;">False</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #ff7fff;">self</span>.<span style="color: white;">get</span><span style="color: white;">&#40;</span><span style="color: #b7c274;">&quot;compactlist&quot;</span>,<span style="color: #ff7fff;">self</span>.__uri,<span style="color: #ff7fff;">self</span>.<span style="color: white;">contactlist</span>.<span style="color: white;">keys</span><span style="color: white;">&#40;</span><span style="color: white;">&#41;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">response = <span style="color: #ff7fff;">self</span>.<span style="color: white;">send</span><span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #23ebc3;">code</span> = <span style="color: #ff7fff;">self</span>.<span style="color: white;">get_code</span><span style="color: white;">&#40;</span>response<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">if</span> <span style="color: #23ebc3;">code</span> <span style="color: #993399;">!</span>= <span style="color: #00baff;color:#800000;">200</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> <span style="color: #ff7fff;">False</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#self.get(&quot;PGGetGroupList&quot;,self.__uri)</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#response = self.send()</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #ff7fff;">self</span>.<span style="color: white;">get_offline_msg</span><span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>这里是获得了好友列表，然后给这些好友发一个上线的通知，如果你不想每次提醒的时飞信上的好友都看到你上线，那么就去掉这些，也会加快发送短信的速度。更进一步的优化，你可以去掉TCP通信的相关代码。</p>
<p>ok, 发挥你的想象力，play with <a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a> and <a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a></p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/12/15/app-use-pyfetion-on-gae/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>PyFetion 0.2 发布</title>
		<link>http://cocobear.info/blog/2009/12/12/pyfetion-02-release/</link>
		<comments>http://cocobear.info/blog/2009/12/12/pyfetion-02-release/#comments</comments>
		<pubDate>Sat, 12 Dec 2009 12:14:05 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[PyFetion]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=743</guid>
		<description><![CDATA[PyFetion 0.2版本发布，协议根据移动09.11.04的飞信版本：Fetion2008 3.5.2(安全加强版) http://code.google.com/p/pytool/ 更新内容包含： 增加查看飞信好友是否隐身功能 增加登录时状态的选择[隐身 在线 忙碌 离开] 日志改用Python的logging模块 增加对好友状态改变的处理( 如上线等) 重写TCP方式中的底层通信函数 使用对列保存接收到的多余消息( 例如发短信时本来应该返回200 OK 却先来了个BN通知消息，以前这样会出错，现在底层会把BN消息放在队列中，返回200 OK) 修改了一些异常处理方式 增加登出，删除好友函数 改写get_contactlist函数，使用一个dict保存当前的好友列表 增加一个receive函数 做客户端的时候可以在一个线程中主调用该函数，所有的消息都会yield出来(请参考fetion.py) 修正向PC发送消息的命令，飞信新增加了一个CatMsg的命令 增加接收从最新版本PC端发送的消息功能;这个比较麻烦新版本飞信对每一个新会话使用fork出一个线程的方式; John先给服务器说我要开个新会话，服务应答一个消息说，你去这个IP吧，带着这个密钥 于是John就连到了这个IP，并使用这个密钥登录，接着发一个包含Bob的uri的邀请命令; 服务器把这个通知(包含IP 密钥和邀请者John的uri)给Bob，Bob收到服务器的通知后也用同样的密钥登录该IP 这时John收到Bob进入会话的消息，他就开始正式发消息了 许多清理了修正 调整类的结构 改用MIT License 增加了一个CLI的飞信客户端 跨平台支持 Fedora8 Python2.5.1测试;Windowx XP Python2.6.4测试;Win7 Python2.6.2测试;Mac 10.5.7 Python2.5.1 我忘记在这里列出来的 ./fetion.py ------------------------基于PyFetion的一个CLI飞信客户端------------------------- 命令不区分大小写中括号里为命令的缩写 help[?] 显示本帮助信息 ls[l] 列出好友列表 status[st] 改变飞信状态 参数[0隐身 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a> 0.2版本发布，协议根据移动09.11.04的飞信版本：Fetion2008 3.5.2(安全加强版) </p>
<p><a href="http://code.google.com/p/pytool/">http://code.google.com/p/pytool/</a><br />
更新内容包含：</p>
<ol>
<li>增加查看飞信好友是否隐身功能</li>
<li>增加登录时状态的选择[隐身 在线 忙碌 离开]</li>
<li>日志改用<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>的logging模块</li>
<li>增加对好友状态改变的处理( 如上线等)</li>
<li>重写TCP方式中的底层通信函数</li>
<li>使用对列保存接收到的多余消息( 例如发短信时本来应该返回200 OK 却先来了个BN通知消息，以前这样会出错，现在底层会把BN消息放在队列中，返回200 OK)</li>
<li>修改了一些异常处理方式</li>
<li>增加登出，删除好友函数</li>
<li>改写get_contactlist函数，使用一个dict保存当前的好友列表</li>
<li>增加一个receive函数 做客户端的时候可以在一个线程中主调用该函数，所有的消息都会yield出来(请参考fetion.py)</li>
<li>修正向PC发送消息的命令，飞信新增加了一个CatMsg的命令</li>
<li>增加接收从最新版本PC端发送的消息功能;这个比较麻烦新版本飞信对每一个新会话使用fork出一个线程的方式;</li>
<p>        John先给服务器说我要开个新会话，服务应答一个消息说，你去这个IP吧，带着这个密钥<br />
        于是John就连到了这个IP，并使用这个密钥登录，接着发一个包含Bob的uri的邀请命令;<br />
        服务器把这个通知(包含IP 密钥和邀请者John的uri)给Bob，Bob收到服务器的通知后也用同样的密钥登录该IP<br />
        这时John收到Bob进入会话的消息，他就开始正式发消息了</p>
<li>许多清理了修正</li>
<li>调整类的结构</li>
<li>改用MIT License</li>
<li>增加了一个CLI的飞信客户端 跨平台支持</li>
<li>Fedora8 Python2.5.1测试;Windowx XP Python2.6.4测试;Win7 Python2.6.2测试;Mac 10.5.7 Python2.5.1</li>
<li>我忘记在这里列出来的</li>
</ol>
<p>./fetion.py<br />
------------------------基于<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>的一个CLI飞信客户端-------------------------</p>
<p>        命令不区分大小写中括号里为命令的缩写</p>
<p>        help[?]            显示本帮助信息<br />
        ls[l]                列出好友列表<br />
        status[st]        改变飞信状态 参数[0隐身 1离开 2忙碌 3在线]<br />
                             参数为空显示自己的状态<br />
        msg[m]           发送消息 参数为序号或手机号 使用quit退出<br />
        sms[s]            发送短信 参数为序号或手机号 使用quit退出<br />
                             参数为空给自己发短信<br />
        find[f]            查看好友是否隐身 参数为序号或手机号<br />
        add[a]           添加好友 参数为手机号或飞信号<br />
        del[d]            删除好友 参数为手机号或飞信号<br />
        cls[c]            清屏<br />
        quit[q]           退出对话状态<br />
        exit[x]           退出飞信</p>
<p>fetion.py特色:</p>
<ol>
<li>多线程支持，同时收发消息</li>
<li>添加，删除，好友，判断好友是否隐身功能</li>
<li>占用资源少，我正写这博客的时候官方的飞信占我96.8M的内存</li>
<li>跨平台支持</li>
<li>扩展性好，加两行代码就可以实现从手机发命令关机等功能</li>
<li>其它我没发现的</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/12/12/pyfetion-02-release/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>Google Map</title>
		<link>http://cocobear.info/blog/2009/08/04/google-map/</link>
		<comments>http://cocobear.info/blog/2009/08/04/google-map/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 01:22:56 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[map]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=723</guid>
		<description><![CDATA[Google Map的算法分析见:http://www.codeproject.com/KB/scrapbook/googlemap.aspx Google Map使用http://mt[0-3].google.cn/mt/v=cn1.11&#038;hl=zh-CN&#038;x=%d&#038;y=%d&#038;z=%d&#038;s=Galile这样的URL来表示一个放大等级中最小的地图分块。 mt0----mt3是四个Google Map的服务器 v=cn1.11 是当前地图的版本 一直在变化中 x,y,z分别代表当前分块所在位置和放大等级，Z=19为最大的放大等级，目前很多城市都可以查看到该等级下的地图 在某个放大等级z下，整个地球被分成2^z分块 x,y可以根据经纬度来计算;x的计算比较好理解(longitude->经度)： longitude=180+longitude #修正经度值到0-360 因为经度的表示是从-180--->180 longTileSize=360.0/(pow(2,zoom)) #计算每个分块所占的角度数 tilex = longitude/longTileSize #计算当前经度所在的分块位置 y的计算要牵扯到墨卡托投影这个地图算法，比较麻烦没看懂。不过并不影响使用，相应的代码上面已经给出来了，然后就可以用Python下载地图分块，使用PIL库把分块合并。 代码见Google Code (这个是西安地图)： #GMap2Png(108.80824,34.37075,109.10316,34.15366,16) 参数为你需要确定的图片左上角的经纬度和右下角的经纬度 最后一个是放大的等级 使用的时候需要注意如果你选择的经纬度范围较大，那么放大等级就不能太大，不然要生成一个巨大图片，PIL会报MemoryError的错误。 还有些问题我在CPyUG记录了下来，不过没使用好的解决方案。]]></description>
			<content:encoded><![CDATA[<p>Google <a href="http://cocobear.info/blog/tag/map/" class="st_tag internal_tag" rel="tag" title="Posts tagged with map">Map</a>的算法分析见:<a href="http://www.codeproject.com/KB/scrapbook/googlemap.aspx">http://www.codeproject.com/KB/scrapbook/googlemap.aspx</a></p>
<p>Google <a href="http://cocobear.info/blog/tag/map/" class="st_tag internal_tag" rel="tag" title="Posts tagged with map">Map</a>使用http://mt[0-3].google.cn/mt/v=cn1.11&#038;hl=zh-CN&#038;x=%d&#038;y=%d&#038;z=%d&#038;s=Galile这样的URL来表示一个放大等级中最小的地图分块。<br />
mt0----mt3是四个Google <a href="http://cocobear.info/blog/tag/map/" class="st_tag internal_tag" rel="tag" title="Posts tagged with map">Map</a>的服务器<br />
v=cn1.11 是当前地图的版本 一直在变化中<br />
x,y,z分别代表当前分块所在位置和放大等级，Z=19为最大的放大等级，目前很多城市都可以查看到该等级下的地图<br />
    在某个放大等级z下，整个地球被分成2^z分块<br />
    x,y可以根据经纬度来计算;x的计算比较好理解(longitude->经度)：<br />
    longitude=180+longitude                     #修正经度值到0-360 因为经度的表示是从-180--->180<br />
    longTileSize=360.0/(pow(2,zoom))        #计算每个分块所占的角度数<br />
    tilex =  longitude/longTileSize               #计算当前经度所在的分块位置</p>
<p>y的计算要牵扯到墨卡托投影这个地图算法，比较麻烦没看懂。不过并不影响使用，相应的代码上面已经给出来了，然后就可以用<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>下载地图分块，使用PIL库把分块合并。</p>
<p>代码见<a href="http://code.google.com/p/pytool/source/browse/trunk/GMap2Png.py">Google Code</a></p>
<p>(这个是西安地图)：<br />
#GMap2Png(108.80824,34.37075,109.10316,34.15366,16)<br />
参数为你需要确定的图片左上角的经纬度和右下角的经纬度 最后一个是放大的等级<br />
使用的时候需要注意如果你选择的经纬度范围较大，那么放大等级就不能太大，不然要生成一个巨大图片，PIL会报MemoryError的错误。</p>
<p>还有些问题我在<a href="https://groups.google.com/group/python-cn/browse_thread/thread/15a19893a7aa503b/b9c8fa6be0056a5f#b9c8fa6be0056a5f">CPyUG</a>记录了下来，不过没使用好的解决方案。</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/08/04/google-map/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>多资源、多线程、断点续传</title>
		<link>http://cocobear.info/blog/2009/06/02/multi-thread-and-broken-point-resume-technology/</link>
		<comments>http://cocobear.info/blog/2009/06/02/multi-thread-and-broken-point-resume-technology/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 09:22:59 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=697</guid>
		<description><![CDATA[我要做一个支持多资源、多线程、断点续传的小工具，基于Python。Windows下有迅雷、FlashGet、QQ旋风（相当地泛滥），Linux下也有D4X,Axel ,aria2，那为什么还要写这样一个工具呢？ (1) 上面都不是Python写的。 (2) Linux下的下载工具都不能主动获取资源，而现在迅雷和FlashGet之所以快就是因为他们有资源。 (3) Linux下几个工具多线程、断点续传做的不太好。aria2似乎不错，不过我没编译过去，支持那么多协议，觉得有点臃肿。 其实从原理上讲，迅雷不过就是一个HTTP/FTP的多线程断点下载工具，现在做大了就来抢BT、电驴的用户，把这两个协议也加了进去。 前段时间看过axel，它的实现太简单了，只是固定的产生N个线程，然后把文件分成N块交给这些线程去下载。从迅雷的配置文件和下载的日志中可以看出来迅雷对下载文件的分块和线程的使用是有自己独有的方式（它线程下载的数据块有时很大4M，有时很小32K，即使在同一个线程中也是这样），我没办法知道迅雷是怎么做这个工作。所以我只能通过猜测和自己的一些想法来做这个工作。尽可能的保证合理的分块和线程使用。 创建一个下载管理器，包括配置信息，任务列表，一个具有速度值与使用次数的URL列表。 首先得到下载文件的大小(filesize)，然后根据配置以及获得的URL数(N)对文件进行分块。 设置一个最小的分块值 MinPiece = 1024*128 （最小分块大于filesize的5%） 设置一个最大的分块值 MaxPiece = 1024*1024*200 if filesize < = MinPiece: 不进行分块。选第一个地址进行下载，如果该地址下载超时则使用其它地址下载。（是否可以考虑使用N个地址同时下载？） elif: 把文件分为N块，每块大小为Piece。 if Piece < MinPiece 把文件分为N-1块，Until Piece > MinPiece if Piece > MaxPiece 把文件分为N+1块，Until Piece < MaxPiece 生成任务列表，一个任务包括:URL,filename,range[start,pos,end] 任务列表中对任务进行标记，DONE，RUNNING,PAUSE,STOP(需要这么多吗？) 根据获得的资源数产生N线程的线程池。 逐步向线程池中增加线程：前提是所有线程成功运行，则增加一个线程。 每个URL对应一个线程的上限数（5），总使用线程数固定（35） 线程运行时检查是否有空闲线程，如果有，则把自己的任务分割（分割的办法使用折半方式，同时要保证分块大于MinPiece），放在任务列表中，同时修改自己的任务的分段信息。 加入任务列表时从URL列表中选一个速度较快的URL，且该URL线程数未达到上限。（如何判断是否达到服务器支持连接数上限？如果针对某个URL创建新连接失败则标记该URL为不可再连接） 线程运行时检查缓冲区的大小，当大于write_buffer_size时则写文件（大于文件的10%时也写？），并且写记录文件，更新URL列表中的速度值，做这些操作时要使用锁机制。这个write_buffer_size根据不同的文件对应不同的大小（2M--->16M迅雷使用8-256）。写文件时可以直接seek到需要写入的位置，如果操作系统不支持这种方式，则先用0填充文件。 线程对失效的URL进行标记，对不支持断点续传的URL进行标记。考虑GBK,UTF-8编码。 线程完成时与停止时做写文件操作与上面操作相同。 [...]]]></description>
			<content:encoded><![CDATA[<p>我要做一个支持多资源、多线程、断点续传的小工具，基于<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>。Windows下有迅雷、FlashGet、QQ旋风（相当地泛滥），Linux下也有D4X,Axel ,aria2，那为什么还要写这样一个工具呢？</p>
<p>(1) 上面都不是<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>写的。<br />
(2) Linux下的下载工具都不能主动获取资源，而现在迅雷和FlashGet之所以快就是因为他们有资源。<br />
(3) Linux下几个工具多线程、断点续传做的不太好。aria2似乎不错，不过我没编译过去，支持那么多协议，觉得有点臃肿。</p>
<p>其实从原理上讲，迅雷不过就是一个HTTP/FTP的多线程断点下载工具，现在做大了就来抢BT、电驴的用户，把这两个协议也加了进去。</p>
<p>前段时间看过axel，它的实现太简单了，只是固定的产生N个线程，然后把文件分成N块交给这些线程去下载。从迅雷的配置文件和下载的日志中可以看出来迅雷对下载文件的分块和线程的使用是有自己独有的方式（它线程下载的数据块有时很大4M，有时很小32K，即使在同一个线程中也是这样），我没办法知道迅雷是怎么做这个工作。所以我只能通过猜测和自己的一些想法来做这个工作。尽可能的保证合理的分块和线程使用。</p>
<p>创建一个下载管理器，包括配置信息，任务列表，一个具有速度值与使用次数的URL列表。</p>
<p>首先得到下载文件的大小(filesize)，然后根据配置以及获得的URL数(N)对文件进行分块。<br />
设置一个最小的分块值 MinPiece = 1024*128 （最小分块大于filesize的5%）<br />
设置一个最大的分块值 MaxPiece = 1024*1024*200</p>
<p>if filesize < = MinPiece:<br />
不进行分块。选第一个地址进行下载，如果该地址下载超时则使用其它地址下载。（是否可以考虑使用N个地址同时下载？）</p>
<p>elif:<br />
把文件分为N块，每块大小为Piece。<br />
if Piece < MinPiece<br />
把文件分为N-1块，Until Piece > MinPiece</p>
<p>if Piece > MaxPiece<br />
把文件分为N+1块，Until Piece < MaxPiece</p>
<p>生成任务列表，一个任务包括:URL,filename,range[start,pos,end]<br />
任务列表中对任务进行标记，DONE，RUNNING,PAUSE,STOP(需要这么多吗？)</p>
<p>根据获得的资源数产生N线程的线程池。</p>
<p>逐步向线程池中增加线程：前提是所有线程成功运行，则增加一个线程。<br />
每个URL对应一个线程的上限数（5），总使用线程数固定（35）</p>
<p>线程运行时检查是否有空闲线程，如果有，则把自己的任务分割（分割的办法使用折半方式，同时要保证分块大于MinPiece），放在任务列表中，同时修改自己的任务的分段信息。<br />
加入任务列表时从URL列表中选一个速度较快的URL，且该URL线程数未达到上限。（如何判断是否达到服务器支持连接数上限？如果针对某个URL创建新连接失败则标记该URL为不可再连接）</p>
<p>线程运行时检查缓冲区的大小，当大于write_buffer_size时则写文件（大于文件的10%时也写？），并且写记录文件，更新URL列表中的速度值，做这些操作时要使用锁机制。这个write_buffer_size根据不同的文件对应不同的大小（2M--->16M迅雷使用8-256）。写文件时可以直接seek到需要写入的位置，如果操作系统不支持这种方式，则先用0填充文件。</p>
<p>线程对失效的URL进行标记，对不支持断点续传的URL进行标记。考虑GBK,UTF-8编码。<br />
线程完成时与停止时做写文件操作与上面操作相同。</p>
<p>记录文件中保存任务列表：<br />
URL,filename,range[start,pos,end]<br />
这样续传的时候程序就根据记录文件载入所有的任务，然后开启线程，进行下载。<br />
记录文件使用MD5校验（最后一行存放前面信息的MD5值）。</p>
<p>一个线程如果速度过慢，则释放当前的任务，把它扔回任务列表中，标记该URL很慢，由空闲的线程再次开启这个任务，这时候有可能又由这个线程接管，但是使用的URL不同，因为扔回任务列表的时候会先一个较快的URL。</p>
<p>HTTP请求需要设置一个超时时间。</p>
<p>----------------------------------------------------------------------<br />
只是把我的一些想法在这里先记录下来，所以比较乱，做的时候可能还会有些变化。至少我目前觉得这种设计方式还是比较智能和高效的，欢迎大家拍砖，如果有好的建议我会记录下来。</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/06/02/multi-thread-and-broken-point-resume-technology/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>pythunder又写了一遍</title>
		<link>http://cocobear.info/blog/2009/05/04/rewrite-pythunder/</link>
		<comments>http://cocobear.info/blog/2009/05/04/rewrite-pythunder/#comments</comments>
		<pubDate>Mon, 04 May 2009 08:25:31 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[pythunder]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=628</guid>
		<description><![CDATA[前几天在Python中文件邮件列表里看到讨论使用Python实现迅雷，后来又在Ubuntu论坛看到一个贴子，实现了获取迅雷服务器上的侯选资源（不是开源的）。突然就对这个迅雷协议很感兴趣，在别人分析的基础上用Python写了个小工具，与Ubuntu论坛上那个作用是一样的，获取迅雷服务器上的侯选资源。 迅雷有多个资源服务器，有的资源服务器返回完全一样，有的返回某些一样，这样可以指定多个服务器，获取更多的资源，同时也可以防止某个服务器不能正常响应。 用webpy写了个演示面面： http://cocobear.info/demo/pythunder/?url=http://3.duote.com/xunleidt.exe 不知道开源了会不会产生麻烦？ ---------------------------------解释下标题------------------------------ 前几天拿U盘做产量的时候没把代码备份出来，所以原本已经写好了今天又写了一遍，幸好代码很短:-)]]></description>
			<content:encoded><![CDATA[<p>前几天在<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>中文件邮件列表里看到讨论<a href="http://groups.google.com/group/python-cn/browse_thread/thread/bed99d33bfd76af9">使用Python实现迅雷</a>，后来又在Ubuntu论坛看到<a href="http://forum.ubuntu.org.cn/viewtopic.php?f=73&#038;t=195557">一个贴子</a>，实现了获取迅雷服务器上的侯选资源（不是开源的）。突然就对这个迅雷协议很感兴趣，在<a href="http://hi.baidu.com/vessial/blog/item/eccb62dc844dd1a4cc11662d.html">别人分析</a>的基础上用<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>写了个小工具，与Ubuntu论坛上那个作用是一样的，获取迅雷服务器上的侯选资源。</p>
<p>迅雷有多个资源服务器，有的资源服务器返回完全一样，有的返回某些一样，这样可以指定多个服务器，获取更多的资源，同时也可以防止某个服务器不能正常响应。</p>
<p>用webpy写了个演示面面：</p>
<p>http://cocobear.info/demo/<a href="http://cocobear.info/blog/tag/pythunder/" class="st_tag internal_tag" rel="tag" title="Posts tagged with pythunder">pythunder</a>/?url=http://3.duote.com/xunleidt.exe</p>
<p>不知道开源了会不会产生麻烦？</p>
<p>---------------------------------解释下标题------------------------------<br />
前几天拿U盘做产量的时候没把代码备份出来，所以原本已经写好了今天又写了一遍，幸好代码很短:-)</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/05/04/rewrite-pythunder/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>关于PyFetion不能在GAE上使用</title>
		<link>http://cocobear.info/blog/2009/04/25/pyfetion-can-not-use-in-gae/</link>
		<comments>http://cocobear.info/blog/2009/04/25/pyfetion-can-not-use-in-gae/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 09:56:36 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[编程相关]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[PyFetion]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=617</guid>
		<description><![CDATA[最近有同学反映PyFetion不能在GAE上使用，我看了下别人给出的错误，问题不出在PyFetion上，无论是TCP方式还是HTTP方式，使用本机测试都可以正常工作。 应该是移动的飞信服务器屏蔽了GAE的出口IP地址（某同学反应GAE的urlopen使用的是同一IP）。 原因大概是广大GAE的爱好者众多，玩PyFetion的又比较多，所以移动不爽了，就封掉你。 问题出来了，原因也大概知道了，那怎么解决方案呢，下面就给出几个吧: 强烈要求GAE增加代理支持。 打电话给10086，然后说你的飞信上不出了，然后给客服MM说你的IP是:[GAE_IP(哪位知道这个IP来补充一下)]。 脱离GAE，使用自己的服务器。 继续使用GAE，使用另一服务器做为跳板。 解释一下，GAE不能直接访问飞信服务器了，可以在另一个地方，比如cocobear.info/PyFetion.py?phone=13838381438&#038;pwd=383838&#038;msg=^_^ 做这样的一个的接口，然后使用GAE去访问这个服务器。 Update(09.4.27): 据gohsy同学反映，GAE上不能使用是因为服务器返回了405错误，而别的fetion实现会忽略405错误，继续进行，而PyFetion遇到这个错误会产生异常。记得以前调PyFetion的时候也遇到过405错误，应该是发送的数据格式不对而造成的，所以我猜想这里是因为网络环境影响造成的数据不完整，从而使得飞信服务器返回405错误。因为在GAE上PyFetion还是可以偶尔发送成功的，所以出错的原因应该不是程序本身。 为了在GAE上能更好的使用，我修改了一下PyFetion，增加了遇到405错误时重试功能，默认重试5次，这样会使得发送的成功率提高很多，但是由于405的出现，重试多次会影响到发送的速度，这一点是无法避免的。更新请到google code查看:http://code.google.com/p/pytool/source/detail?r=30 其实根本的原因我想还是GAE上用PyFetion的人过多造成的:-) 为了在GAE上调PyFetion，在gohsy同学的帮助下，搭建了GAE环境，感觉还不错，做应用挺方便的，不错的东东。]]></description>
			<content:encoded><![CDATA[<p>最近<a href="http://cocobear.info/blog/2009/02/20/upgrade-pyfetion/">有同学反映</a><a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>不能在<a href="http://code.google.com/appengine/">GAE</a>上使用，我看了下别人给出的错误，问题不出在<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>上，无论是TCP方式还是HTTP方式，使用本机测试都可以正常工作。<br />
应该是移动的飞信服务器屏蔽了<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>的出口IP地址（某同学反应<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>的urlopen使用的是同一IP）。</p>
<p>原因大概是广大<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>的爱好者众多，玩<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>的又比较多，所以移动不爽了，就封掉你。</p>
<p>问题出来了，原因也大概知道了，那怎么解决方案呢，下面就给出几个吧:</p>
<ol>
<li>强烈要求<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>增加代理支持。</li>
<li>打电话给10086，然后说你的飞信上不出了，然后给客服MM说你的IP是:[GAE_IP(哪位知道这个IP来补充一下)]。</li>
<li>脱离<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>，使用自己的服务器。</li>
<li>继续使用<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>，使用另一服务器做为跳板。</li>
<p>        解释一下，<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>不能直接访问飞信服务器了，可以在另一个地方，比如cocobear.info/<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>.py?phone=13838381438&#038;pwd=383838&#038;msg=^_^<br />
       做这样的一个的接口，然后使用<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>去访问这个服务器。</p>
</ol>
<p>Update(09.4.27):<br />
据gohsy同学反映，<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上不能使用是因为服务器返回了405错误，而别的fetion实现会忽略405错误，继续进行，而<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>遇到这个错误会产生异常。记得以前调<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>的时候也遇到过405错误，应该是发送的数据格式不对而造成的，所以我猜想这里是因为网络环境影响造成的数据不完整，从而使得飞信服务器返回405错误。因为在<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>还是可以偶尔发送成功的，所以出错的原因应该不是程序本身。</p>
<p>为了在<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上能更好的使用，我修改了一下<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>，增加了遇到405错误时重试功能，默认重试5次，这样会使得发送的成功率提高很多，但是由于405的出现，重试多次会影响到发送的速度，这一点是无法避免的。更新请到google code查看:<a href="http://code.google.com/p/pytool/source/detail?r=30">http://code.google.com/p/pytool/source/detail?r=30</a></p>
<p>其实根本的原因我想还是<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上用<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>的人过多造成的:-)</p>
<p>为了在<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>上调<a href="http://cocobear.info/blog/tag/pyfetion/" class="st_tag internal_tag" rel="tag" title="Posts tagged with PyFetion">PyFetion</a>，在gohsy同学的帮助下，搭建了<a href="http://cocobear.info/blog/tag/gae/" class="st_tag internal_tag" rel="tag" title="Posts tagged with gae">GAE</a>环境，感觉还不错，做应用挺方便的，不错的东东。</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/04/25/pyfetion-can-not-use-in-gae/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
		<item>
		<title>Python与Lua中的尾部调用优化</title>
		<link>http://cocobear.info/blog/2009/03/31/tail-call-optimization-in-python-lua/</link>
		<comments>http://cocobear.info/blog/2009/03/31/tail-call-optimization-in-python-lua/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 06:23:12 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Lua]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=595</guid>
		<description><![CDATA[LUA: &#62; &#160; &#160; function foo &#40;n&#41; &#62;&#62; &#160; &#160; &#160; if n&#62; 0 then return foo&#40;n - 1&#41; end &#62;&#62; &#160; &#160; end &#62; foo&#40;100&#41; &#62; foo&#40;1000&#41; &#62; foo&#40;10000&#41; &#62; foo&#40;100000&#41; &#62; foo&#40;1000000&#41; 如果函数最后一句是return g(...)这样的形式，Lua将会把这句解释为goto g(x)，因为这里除了对g函数调用，再没有别的事做，也不需要保存堆栈里调用函数的信息。因此上面即使调用很多次也没有出现堆栈溢出的问题，把上面的代码转换为Python: PYTHON: &#62;&#62;&#62; def foo&#40;n&#41;: ... &#160; &#160; if n&#62;0: return foo&#40;n-1&#41; ... &#62;&#62;&#62; foo&#40;100&#41; &#62;&#62;&#62; foo&#40;1000&#41; ... &#160; [...]]]></description>
			<content:encoded><![CDATA[<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">LUA</a>:</span>
<div id="lua-15">
<div class="lua" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> &nbsp; &nbsp; <span style="color: #4e4eff;">function</span> foo <span style="color: #993399;">&#40;</span>n<span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; &nbsp; <span style="color: #4e4eff;">if</span> n<span style="color: #993399;">&gt;</span> <span style="color: #339933;color:#800000;">0</span> <span style="color: #4e4eff;">then</span> <span style="color: #4e4eff;">return</span> foo<span style="color: #993399;">&#40;</span>n - <span style="color: #339933;color:#800000;">1</span><span style="color: #993399;">&#41;</span> <span style="color: #4e4eff;">end</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; <span style="color: #4e4eff;">end</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> foo<span style="color: #993399;">&#40;</span><span style="color: #339933;color:#800000;">100</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> foo<span style="color: #993399;">&#40;</span><span style="color: #339933;color:#800000;">1000</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> foo<span style="color: #993399;">&#40;</span><span style="color: #339933;color:#800000;">10000</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> foo<span style="color: #993399;">&#40;</span><span style="color: #339933;color:#800000;">100000</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> foo<span style="color: #993399;">&#40;</span><span style="color: #339933;color:#800000;">1000000</span><span style="color: #993399;">&#41;</span></div>
</li>
</ol>
</div>
</div>
</div>
<p>
如果函数最后一句是return g(...)这样的形式，<a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a>将会把这句解释为goto g(x)，因为这里除了对g函数调用，再没有别的事做，也不需要保存堆栈里调用函数的信息。因此上面即使调用很多次也没有出现堆栈溢出的问题，把上面的代码转换为<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-16">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;&gt;</span> <span style="color: #0088ff;font-weight:bold;">def</span> foo<span style="color: white;">&#40;</span>n<span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">... &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">if</span> n<span style="color: #993399;">&gt;</span><span style="color: #00baff;color:#800000;">0</span>: <span style="color: #0088ff;font-weight:bold;">return</span> foo<span style="color: white;">&#40;</span>n-<span style="color: #00baff;color:#800000;">1</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">... </div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;&gt;</span> foo<span style="color: white;">&#40;</span><span style="color: #00baff;color:#800000;">100</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;&gt;</span> foo<span style="color: white;">&#40;</span><span style="color: #00baff;color:#800000;">1000</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">...</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: white;">File</span> <span style="color: #b7c274;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #00baff;color:#800000;">2</span>, <span style="color: #0088ff;font-weight:bold;">in</span> foo</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; File <span style="color: #b7c274;">&quot;&lt;/stdin&gt;&lt;stdin&gt;&quot;</span>, line <span style="color: #00baff;color:#800000;">2</span>, <span style="color: #0088ff;font-weight:bold;">in</span> foo</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; File <span style="color: #b7c274;">&quot;&lt;/stdin&gt;&lt;stdin&gt;&quot;</span>, line <span style="color: #00baff;color:#800000;">2</span>, <span style="color: #0088ff;font-weight:bold;">in</span> foo</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #ff7fff;">RuntimeError</span>: maximum recursion depth exceeded</div>
</li>
</ol>
</div>
</div>
</div>
<p>
很快出就现了堆栈溢出的问题，在这里表现为达到了递归调用的最大限制。<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>自身没有实现尾部调用优化，不过也可以通过实现一个decorator办法来实现:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-17">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;">#!/usr/bin/env python2.4</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># This program shows off a <a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">python</a> decorator(</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># which implements tail call optimization. It</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># does this by throwing an exception if it is </span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># it's own grandparent, and catching such </span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># exceptions to recall the stack.</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">import</span> <span style="color: #23ebc3;">sys</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">class</span> TailRecurseException:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">def</span> <span style="color: #ffff32;">__init__</span><span style="color: white;">&#40;</span><span style="color: #ff7fff;">self</span>, args, kwargs<span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #ff7fff;">self</span>.<span style="color: white;">args</span> = args</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #ff7fff;">self</span>.<span style="color: white;">kwargs</span> = kwargs</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">def</span> tail_call_optimized<span style="color: white;">&#40;</span>g<span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #b7c274;">&quot;&quot;&quot;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;This function decorates a function with tail call</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;optimization. It does this by throwing an exception</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;if it is it's own grandparent, and catching such</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;exceptions to fake the tail call optimization.</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;This function fails if the decorated</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;function recurses in a non-tail context.</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #b7c274;"> &nbsp;&quot;&quot;&quot;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">def</span> func<span style="color: white;">&#40;</span><span style="color: #993399;">*</span>args, <span style="color: #993399;">**</span>kwargs<span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; f = <span style="color: #23ebc3;">sys</span>._getframe<span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">if</span> f.<span style="color: white;">f_back</span> <span style="color: #0088ff;font-weight:bold;">and</span> f.<span style="color: white;">f_back</span>.<span style="color: white;">f_back</span> </div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">and</span> f.<span style="color: white;">f_back</span>.<span style="color: white;">f_back</span>.<span style="color: white;">f_code</span> == f.<span style="color: white;">f_code</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">raise</span> TailRecurseException<span style="color: white;">&#40;</span>args, kwargs<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">else</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">while</span> <span style="color: #00baff;color:#800000;">1</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">try</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> g<span style="color: white;">&#40;</span><span style="color: #993399;">*</span>args, <span style="color: #993399;">**</span>kwargs<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">except</span> TailRecurseException, e:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; args = e.<span style="color: white;">args</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kwargs = e.<span style="color: white;">kwargs</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; func.__doc__ = g.__doc__</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> func</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">@tail_call_optimized</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">def</span> factorial<span style="color: white;">&#40;</span>n, acc=<span style="color: #00baff;color:#800000;">1</span><span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #b7c274;">&quot;calculate a factorial&quot;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">if</span> n == <span style="color: #00baff;color:#800000;">0</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> acc</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> factorial<span style="color: white;">&#40;</span>n-<span style="color: #00baff;color:#800000;">1</span>, n<span style="color: #993399;">*</span>acc<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">print</span> factorial<span style="color: white;">&#40;</span><span style="color: #00baff;color:#800000;">10000</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># prints a big, big number,</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># but doesn't hit the recursion limit.</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">@tail_call_optimized</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">def</span> fib<span style="color: white;">&#40;</span>i, current = <span style="color: #00baff;color:#800000;">0</span>, next = <span style="color: #00baff;color:#800000;">1</span><span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">if</span> i == <span style="color: #00baff;color:#800000;">0</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> current</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #0088ff;font-weight:bold;">else</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> fib<span style="color: white;">&#40;</span>i - <span style="color: #00baff;color:#800000;">1</span>, next, current + next<span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">print</span> fib<span style="color: white;">&#40;</span><span style="color: #00baff;color:#800000;">10000</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># also prints a big number,</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #7f7f7f; font-style: italic;"># but doesn't hit the recursion limit.</span></div>
</li>
</ol>
</div>
</div>
</div>
<p>
代码来自<a href="http://code.activestate.com/recipes/474088/">http://code.activestate.com/recipes/474088/</a></p>
<p>在这段代码里tail_call_optimized是一个decorator，在执行factorial函数前，这个decorator先执行，tail_call_optimized中通过sys._getframe()这个方法会返回一个frame对象，包含了堆栈顶部的信息，当发现当前调用是一个递归调用:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-18">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #0088ff;font-weight:bold;">if</span> f.<span style="color: white;">f_back</span> <span style="color: #0088ff;font-weight:bold;">and</span> f.<span style="color: white;">f_back</span>.<span style="color: white;">f_back</span> </div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">and</span> f.<span style="color: white;">f_back</span>.<span style="color: white;">f_back</span>.<span style="color: white;">f_code</span> == f.<span style="color: white;">f_code</span>:</div>
</li>
</ol>
</div>
</div>
</div>
<p>
则抛出一个异常，下面的代码则截获异常，继续执行，这样就避免了堆栈的使用，很巧妙的一种方式。</p>
<p>在<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">python</a>-dev的邮件列表里，有人曾经做过一个<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>的尾调用优化的<a href="http://mail.python.org/pipermail/python-dev/2004-July/046150.html">补丁</a>，不过Guido拒绝了这个补丁:</p>
<blockquote><p>I'm not interested in adding this to the official <a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a> release.</p>
<p>One reason is that if an exception happens in such a tail-recursive<br />
call, the stack trace will be confusing.</p>
<p>Another reason is that I don't think it's a good idea to try to<br />
encourage a Scheme-ish "solve everything with recursion" programming<br />
style in <a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>.</p>
<p>But feel free to maintain this as an independent modification, a la<br />
Stackless -- I'm sure there are people who would like to try this<br />
out.</p>
<p>--Guido van Rossum (home page: http://www.<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">python</a>.org/~guido/)</p></blockquote>
<p></stdin></p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/03/31/tail-call-optimization-in-python-lua/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Python与Lua分别实现一个计数器</title>
		<link>http://cocobear.info/blog/2009/03/31/write-a-counter-with-python-and-lua/</link>
		<comments>http://cocobear.info/blog/2009/03/31/write-a-counter-with-python-and-lua/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 04:47:15 +0000</pubDate>
		<dc:creator>可可熊</dc:creator>
				<category><![CDATA[Lua]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://cocobear.info/blog/?p=591</guid>
		<description><![CDATA[Lua: LUA: &#62; &#160; function newCounter &#40;&#41; &#62;&#62; &#160; &#160; local i = 0 &#62;&#62; &#160; &#160; return function &#40;&#41; &#160; -- anonymous function &#62;&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#160;i = i + 1 &#62;&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#160;return i &#62;&#62; &#160; &#160; &#160; &#160; &#160; &#160;end &#62;&#62; &#160; end [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a>:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">LUA</a>:</span>
<div id="lua-21">
<div class="lua" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> &nbsp; <span style="color: #4e4eff;">function</span> newCounter <span style="color: #993399;">&#40;</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; <span style="color: #4e4eff;">local</span> i <span style="color: #993399;">=</span> <span style="color: #339933;color:#800000;">0</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; <span style="color: #4e4eff;">return</span> <span style="color: #4e4eff;">function</span> <span style="color: #993399;">&#40;</span><span style="color: #993399;">&#41;</span> &nbsp; <span style="color: #7f7f7f; font-style: italic;">-- anonymous function</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i <span style="color: #993399;">=</span> i + <span style="color: #339933;color:#800000;">1</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #4e4eff;">return</span> i</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #4e4eff;">end</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;</span> &nbsp; <span style="color: #4e4eff;">end</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> &nbsp; </div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> &nbsp; c1 <span style="color: #993399;">=</span> newCounter<span style="color: #993399;">&#40;</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> <span style="color: #4e4eff;">print</span><span style="color: #993399;">&#40;</span>c1<span style="color: #993399;">&#40;</span><span style="color: #993399;">&#41;</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #339933;color:#800000;">1</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;</span> <span style="color: #4e4eff;">print</span><span style="color: #993399;">&#40;</span>c1<span style="color: #993399;">&#40;</span><span style="color: #993399;">&#41;</span><span style="color: #993399;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #339933;color:#800000;">2</span></div>
</li>
</ol>
</div>
</div>
</div>
<p>
<a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a>同<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>类似，也可以嵌套定义函数，不过<a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a>嵌套函数可以访问上层闭包函数的局部变量，而在这个内嵌函数中这些变量不是全局变量，也不是局部变量，而是一种upvalue，与C语言中的static修饰的变量类似，所以在这里可以利用这个特性完成这个计数器。</p>
<p><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>:</p>
<div class="syntax_hilite"><span class="langName"><a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">PYTHON</a>:</span>
<div id="python-22">
<div class="python" style="font-family:monospace;">
<ol>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #993399;">&gt;&gt;&gt;</span> <span style="color: #0088ff;font-weight:bold;">def</span> counter<span style="color: white;">&#40;</span>last=<span style="color: white;">&#91;</span><span style="color: #00baff;color:#800000;">1</span><span style="color: white;">&#93;</span><span style="color: white;">&#41;</span>:</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; ... &nbsp; &nbsp; <span style="color: white;">next</span> = last<span style="color: white;">&#91;</span><span style="color: #00baff;color:#800000;">0</span><span style="color: white;">&#93;</span> + <span style="color: #00baff;color:#800000;">1</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; ... &nbsp; &nbsp; <span style="color: white;">last</span><span style="color: white;">&#91;</span><span style="color: #00baff;color:#800000;">0</span><span style="color: white;">&#93;</span> = next</div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; ... &nbsp; &nbsp; <span style="color: #0088ff;font-weight:bold;">return</span> next</div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; ... </div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;<span style="color: #993399;">&gt;&gt;&gt;</span> counter<span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #00baff;color:#800000;">2</span></div>
</li>
<li style="font-weight: bold; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;<span style="color: #993399;">&gt;&gt;&gt;</span> counter<span style="color: white;">&#40;</span><span style="color: white;">&#41;</span></div>
</li>
<li style="font-weight: normal; vertical-align:top;color:#3A6A8B;">
<div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; <span style="color: #00baff;color:#800000;">3</span></div>
</li>
</ol>
</div>
</div>
</div>
<p>
今天看<a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a>的时候觉得<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>也应该有比较简单的办法写个计数器，找到<a href="http://www.ibm.com/developerworks/library/l-pycon.html">一篇文章</a>介绍这个小技巧，其中有一句话：</p>
<blockquote><p>However, if named parameters are given mutable default values, the parameters can act as persistent memories of previous invocations. Lists, specifically, are handy mutable objects that can conveniently even hold multiple values. </p></blockquote>
<p><a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a>作为一个嵌入式（嵌入到其它语言中）的脚本语言，在很多地方与<a href="http://cocobear.info/blog/tag/python/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Python">Python</a>类似，这几天在看Programming in  <a href="http://cocobear.info/blog/tag/lua/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Lua">Lua</a> 。</p>
]]></content:encoded>
			<wfw:commentRss>http://cocobear.info/blog/2009/03/31/write-a-counter-with-python-and-lua/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
