<?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>Here comes the Sun &#187; python</title>
	<atom:link href="http://sunng.info/blog/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://sunng.info/blog</link>
	<description>47% users on this site use *nix</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:08:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Exaile豆瓣电台插件0.0.11发布</title>
		<link>http://sunng.info/blog/2011/12/exaile%e8%b1%86%e7%93%a3%e7%94%b5%e5%8f%b0%e6%8f%92%e4%bb%b60-0-11%e5%8f%91%e5%b8%83/</link>
		<comments>http://sunng.info/blog/2011/12/exaile%e8%b1%86%e7%93%a3%e7%94%b5%e5%8f%b0%e6%8f%92%e4%bb%b60-0-11%e5%8f%91%e5%b8%83/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 15:56:45 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[Douban]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1083</guid>
		<description><![CDATA[很高兴时隔半年后我继续发布了Exaile豆瓣电台插件的更新，从第一个版本发布到现在已经有一年半的时间，这期间豆瓣电台插件已经陆续出现在Rhythmbox、Banshee等播放器上。作为第一个视图把豆瓣电台移植到本地的尝试，我感到甚是欣慰：） 这次的更新修正了长久依赖困绕用户登录问题，现在我们有一个专门的界面来输入验证码。这个功能要感谢DigitalPig用户在github的报告（鞭策作用），此外，我参考了豆瓣电台banshee插件的实现，节省了研究含验证码登录的时间，感谢。总而言之，没有用户的推动，这个项目也不会坚持这么久。 除此之外，插件还有一些支持了新的豆瓣说的推荐，优化了播放列表载入的策略。 另外值得highlight的是，对应的gnome-shell扩展发布了0.0.2版本，唯一的更新是专辑封面现在会显示在gnome-shell的菜单中。 你可以从github获得最新的插件和gnome-shell扩展： exaile-doubanfm-plugin 0.0.11-captcha: https://github.com/sunng87/exaile-doubanfm-plugin/downloads exaile-doubanfm-gnome-shell-extension 0.0.2: https://github.com/sunng87/exaile-doubanfm-gnome-shell-extension/tarball/0.0.2 安装豆瓣电台插件请参考这里。gnome-shell扩展直接解压至~/.local/share/gnome-shell/extensions/即可 有任何问题都可以在github或这里留言。]]></description>
			<content:encoded><![CDATA[<p>很高兴时隔半年后我继续发布了Exaile豆瓣电台插件的更新，从第一个版本发布到现在已经有一年半的时间，这期间豆瓣电台插件已经陆续出现在Rhythmbox、Banshee等播放器上。作为第一个视图把豆瓣电台移植到本地的尝试，我感到甚是欣慰：）</p>
<p>这次的更新修正了长久依赖困绕用户登录问题，现在我们有一个专门的界面来输入验证码。这个功能要感谢<a href="https://github.com/sunng87/exaile-doubanfm-plugin/issues/8">DigitalPig</a>用户在github的报告（鞭策作用），此外，我参考了<a href="http://code.google.com/p/banshee-doubanfm/">豆瓣电台banshee插件</a>的实现，节省了研究含验证码登录的时间，感谢。总而言之，没有用户的推动，这个项目也不会坚持这么久。<br />
<img src="http://i.imgur.com/cYNrM.png" alt="" /></p>
<p>除此之外，插件还有一些支持了新的豆瓣说的推荐，优化了播放列表载入的策略。</p>
<p>另外值得highlight的是，对应的gnome-shell扩展发布了0.0.2版本，唯一的更新是专辑封面现在会显示在gnome-shell的菜单中。<br />
<img src="http://i.imgur.com/7Q1CP.jpg" alt="" /></p>
<p>你可以从github获得最新的插件和gnome-shell扩展：</p>
<ul>
<li>exaile-doubanfm-plugin 0.0.11-captcha: <a href="https://github.com/sunng87/exaile-doubanfm-plugin/downloads">https://github.com/sunng87/exaile-doubanfm-plugin/downloads</a></li>
<li>exaile-doubanfm-gnome-shell-extension 0.0.2: <a href="https://github.com/sunng87/exaile-doubanfm-gnome-shell-extension/tarball/0.0.2">https://github.com/sunng87/exaile-doubanfm-gnome-shell-extension/tarball/0.0.2</a></li>
<p>安装豆瓣电台插件请参考<a href="https://github.com/sunng87/exaile-doubanfm-plugin/wiki/Installation">这里</a>。gnome-shell扩展直接解压至~/.local/share/gnome-shell/extensions/即可
</ul>
<p>有任何问题都可以在github或这里留言。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/12/exaile%e8%b1%86%e7%93%a3%e7%94%b5%e5%8f%b0%e6%8f%92%e4%bb%b60-0-11%e5%8f%91%e5%b8%83/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>My response to Spark: Visualize your mercurial commit history from commandline</title>
		<link>http://sunng.info/blog/2011/11/my-response-to-spark-visualize-your-mercurial-commit-history-from-commandline/</link>
		<comments>http://sunng.info/blog/2011/11/my-response-to-spark-visualize-your-mercurial-commit-history-from-commandline/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 04:43:11 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1064</guid>
		<description><![CDATA[标题长了些。还是用母语吧。 昨天HackerNews上一个小脚本轰动了，所谓山不在高程序不在小。为了响应这个小脚本，我写了一个更加简单的Mercurial(hg)扩展，帮助你输出hg仓库的提交历史。这个feature和github的直方图有点像，在我看来github的直方图是他们最重要的feature之一，它鞭策着你不断地commit。 安装:将这个脚本放在任意一处，在你的hgrc中添加： [extensions] summary = /path/to/your/script 由于很简单，就不按照mercurial的规范发布了。]]></description>
			<content:encoded><![CDATA[<p>标题长了些。还是用母语吧。</p>
<p>昨天HackerNews上一个<a href="http://news.ycombinator.com/item?id=3237478" target="_blank">小脚本</a>轰动了，所谓山不在高程序不在小。为了响应这个小脚本，我写了一个更加简单的Mercurial(hg)扩展，帮助你输出hg仓库的提交历史。这个feature和github的直方图有点像，在我看来github的直方图是他们最重要的feature之一，它鞭策着你不断地commit。</p>
<p><img src="http://i.imgur.com/ZcEfH.png" alt="hg summary" /></p>
<p><script src="https://gist.github.com/1366606.js"> </script></p>
<p>安装:将这个脚本放在任意一处，在你的hgrc中添加：</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[extensions]<br />
summary = /path/to/your/script</div></div>
<p>由于很简单，就不按照mercurial的规范发布了。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/11/my-response-to-spark-visualize-your-mercurial-commit-history-from-commandline/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Convert a Python function to Java anonymous class</title>
		<link>http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/</link>
		<comments>http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 07:09:59 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=855</guid>
		<description><![CDATA[When calling Java with Jython, anonymous inner class might be an issue because there is no such equivalent in Python. In GUI programming, jython made additional effort on AWT event processing. You can pass a python function as some types &#8230; <a href="http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When calling Java with Jython, anonymous inner class might be an issue because there is no such equivalent in Python.</p>
<p>In GUI programming, jython made additional effort on AWT event processing. You can pass a python function as some types of event listener.</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> change_text<span style="color: black;">&#40;</span>event<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Clicked!'</span><br />
<br />
button <span style="color: #66cc66;">=</span> JButton<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Click Me!'</span><span style="color: #66cc66;">,</span> actionPerformed<span style="color: #66cc66;">=</span>change_text<span style="color: black;">&#41;</span><br />
frame.<span style="color: black;">add</span><span style="color: black;">&#40;</span>button<span style="color: black;">&#41;</span></div></div>
<p>Described in the <a href="http://www.jython.org/jythonbook/en/1.0/GUIApplications.html">Definitive Guide of Jython</a>:</p>
<blockquote><p>This works because Jython is able to automatically recognize events in Java code if they have corresponding addEvent()* and *removeEvent() methods. Jython takes the name of the event and makes it accessible using the nice Python syntax as long as the event methods are public. </p></blockquote>
<p>However, it does not work with Runnable, Callable and many other interfaces designed for anonymous usage.</p>
<p>To solve the incompatibility, I created a small decorator that converts Python function to a Java object.<br />
<script src="https://gist.github.com/947926.js"> </script></p>
<p>Thanks to python&#8217;s dynamic magic, we can create class in runtime and assign modified method to a particular instance. The conversion is performed once the function loaded. Also, you can pass something as arguments to constructor.</p>
<p>With anonymous_class decorator, the example above can be written as:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> javax.<span style="color: black;">swing</span> <span style="color: #ff7700;font-weight:bold;">import</span> JButton<span style="color: #66cc66;">,</span> JFrame<br />
<span style="color: #ff7700;font-weight:bold;">from</span> java.<span style="color: black;">awt</span>.<span style="color: black;">event</span> <span style="color: #ff7700;font-weight:bold;">import</span> ActionListener<br />
<br />
frame <span style="color: #66cc66;">=</span> JFrame<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Hello, Jython!'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaultCloseOperation <span style="color: #66cc66;">=</span> JFrame.<span style="color: black;">EXIT_ON_CLOSE</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">300</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#41;</span><br />
<br />
<span style="color: #66cc66;">@</span>anonymous_class<span style="color: black;">&#40;</span>ActionListener<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;actionPerformed&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">def</span> change_text<span style="color: black;">&#40;</span>dummy<span style="color: #66cc66;">,</span> event<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Clicked!'</span><br />
<br />
button <span style="color: #66cc66;">=</span> JButton<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Click Me!'</span><span style="color: #66cc66;">,</span> actionPerformed<span style="color: #66cc66;">=</span>change_text<span style="color: black;">&#41;</span><br />
frame.<span style="color: black;">add</span><span style="color: black;">&#40;</span>button<span style="color: black;">&#41;</span><br />
frame.<span style="color: black;">visible</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/convert-a-python-function-to-java-anonymous-class/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Don&#039;t repeat yourself: distribute jython package with jip.dist</title>
		<link>http://sunng.info/blog/2011/04/dont-repeat-yourself-distribute-jython-package-with-jip-dist/</link>
		<comments>http://sunng.info/blog/2011/04/dont-repeat-yourself-distribute-jython-package-with-jip-dist/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 15:19:48 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[jip]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/04/dont-repeat-yourself-distribute-jython-package-with-jip-dist/</guid>
		<description><![CDATA[As a new feature in jip 0.4, we can use some helpers from jip.dist to simplify package distribution. With jip.dist, you can define Java dependencies for your jython package. In an environment with jip, dependencies will be automatically installed when &#8230; <a href="http://sunng.info/blog/2011/04/dont-repeat-yourself-distribute-jython-package-with-jip-dist/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As a new feature in <b>jip</b> 0.4, we can use some helpers from <font face="monospace">jip.dist</font> to simplify package distribution. With jip.dist, you can define Java dependencies for your jython package. In an environment with jip, dependencies will be automatically installed when user uses pip to get you package.</p>
<p>We have two different approaches allow you to choose.</p>
<h3>Approach 1, Define dependencies in POM</h3>
<p>This is the standard maven way. To describe your jython package and its dependencies, create a pom.xml in your project. The directory hierarchy looks like:</p>
<pre>
├── app
│&nbsp;&nbsp; ├── module1
│&nbsp;&nbsp; │&nbsp;&nbsp; ├── __init__.py
│&nbsp;&nbsp; ├── core.py
│&nbsp;&nbsp; ├── __init__.py
├── LICENSE
├── MANIFEST.in
├── pom.xml
├── README
└── setup.py
</pre>
<p>In pom.xml, just add dependencies as you do with Maven.</p>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> &lt;<span style="color: #000066;">br</span>=<span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span> &nbsp;xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;<span style="color: #ddbb00;">&amp;gt;</span><br />
<br />
&nbsp; &nbsp; ...<br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.slf4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.6.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.slf4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j-log4j12<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.6.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;repositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>sonatype-oss-sonatype<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://oss.sonatype.org/content/repositories/snapshots/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/repositories<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>You can also define repositories in pom.xml if you use custom repository. (for example, jboss, java.net)</p>
<p>Remember to add pom.xml in your <font face="monospace">MANIFEST.in</font>, to ensure the file will be packaged into source package:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">include pom.xml</div></div>
<h3>Approach 2, Define dependencies with Python</h3>
<p>You may be tired with endless XML configuration. jip allows you to define dependencies with python, just like gradle with groovy.</p>
<p>In your setup.py, add something like:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">requires_java <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #483d8b;">'dependencies'</span>:<span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">## (groupdId, artifactId, version)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'org.slf4j'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'slf4j-api'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'1.6.1'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'org.slf4j'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'slf4j-log4j12'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'1.6.1'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'info.sunng.soldat'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'soldat'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'1.0-SNAPSHOT'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'org.apache.mina'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'mina-core'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'2.0.2'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #483d8b;">'repositories'</span>:<span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'sonatype-oss-snapshot'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'http://oss.sonatype.org/content/repositories/snapshots/'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><br />
<span style="color: black;">&#125;</span></div></div>
<p>Then pass it to <font face="monospace">setup()</font>. The keyword argument <font face="monospace">require_java</font> is jip specific.</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">requires_java</span><span style="color: #66cc66;">=</span>requires_java<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; ...<span style="color: black;">&#41;</span></div></div>
<h3>Use jip&#8217;s setup wrapper</h3>
<p>To use jip&#8217;s power, the only difference is to use <font face="monospace">setup()</font> from <font face="monospace">jip.dist</font> instead of setuptools or distutils.</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> jip.<span style="color: black;">dist</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup</div></div>
<p>Then publish your jython package to Python Cheese Shop:<br />
<font face="monospace">$ jython setup.py sdist upload</font></p>
<p>Internally, jip uses setuptools. So you can still do <font face="monospace">jython setup.py develop</font> .</p>
<p>And jip 0.4 is available under MIT License. You are free to use jip.dist in your code.</p>
<h3>For your user</h3>
<p>You should write a guide forcing users to use your jython application within <a href="http://www.virtualenv.org">virtualenv</a>. And install jip as a prerequisite:<br />
<font face="monospace">$ pip install jip</font></p>
<p>Then simply install your package with pip:<br />
<font face="monospace">$ pip install &lt;your-package-name&gt;</font></p>
<p>No additional step required!</p>
<p>So please just release your jython package with <b>jip</b> !</p>
<p>For more information:</p>
<ul>
<li><a href="http://pypi.python.org/pypi/jip/">http://pypi.python.org/pypi/jip/</a></li>
<li><a href="https://github.com/sunng87/jip">https://github.com/sunng87/jip</a></li>
</ul>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=5c436f7f-49fe-8f60-9a90-1331f01105a9" /></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/dont-repeat-yourself-distribute-jython-package-with-jip-dist/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jip 0.2 released</title>
		<link>http://sunng.info/blog/2011/04/jip-0-2-released/</link>
		<comments>http://sunng.info/blog/2011/04/jip-0-2-released/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 14:29:15 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jip]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/04/jip-0-2-released/</guid>
		<description><![CDATA[As you may know, jip is a dependency management tool for Jython/Java development. It resolves and downloads Java packages from maven-compatible repositories. jip also follows some best practices, encouraging you to use a portable and standalone environment (virtualenv) for your &#8230; <a href="http://sunng.info/blog/2011/04/jip-0-2-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As you may know, jip is a dependency management tool for Jython/Java development. It resolves and downloads Java packages from maven-compatible repositories. jip also follows some best practices, encouraging you to use a portable and standalone environment (virtualenv) for your Jython development.</p>
<p>It has been four months since the initial release. In version 0.2, I made following changes for you:</p>
<ul>
<li>Improved console output format</li>
<li>Correct scope dependency management inheritance</li>
<li>Snapshot management, alpha</li>
<li>Environment independent configuration</li>
<li>Bug fixes</li>
</ul>
<p>You can find the typical usage doc on github:<br />
<a href="https://github.com/sunng87/jip">https://github.com/sunng87/jip</a></p>
<p>jip-0.2 has been published to pypi so you can install or upgrade it with:<br />
easy_install -U jip</p>
<p>Please do remember to use it inside virtualenv!</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=6d854cec-aede-8421-9daa-99288bc44ead" /></div>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/04/jip-0-2-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>gefr API updates</title>
		<link>http://sunng.info/blog/2011/03/gefr-api-updates/</link>
		<comments>http://sunng.info/blog/2011/03/gefr-api-updates/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 13:11:52 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[gefr]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=818</guid>
		<description><![CDATA[早上收到jythonet作者的一封邮件，受到启发，我打算扩展一下gefr这个WSGI adapter。原本gefr是写给soldat用来测试的，结果发现现在出现了买椟还珠的效果，既然大家更加关注这个，我决定多花一些时间在上面。不过话说回来gefr确实是Jython Web程序的新思路，过去大家都在想怎样把Jython放进Servlet中，gefr的思路是把Java的服务器实现放到WSGI后面。未来会有gefr-netty, gefr-mina, gefr-servlet等等出现，如果真的存在一个可靠的backend，也许这种思路也不失为一个办法，毕竟python的web框架更吸引人，而java的基础设施相对可靠，各取所长。 根据这个目的，现在gefr 0.2的API更新为： 即在创建Gefr的时候需要告知backend类型，目前还只有soldat一种后端。未来也可能通过自动检测让这个参数成为可选。 gefr 0.2已经在开发中，您可以通过这里关注： https://bitbucket.org/sunng/gefr/overview]]></description>
			<content:encoded><![CDATA[<p>早上收到<a href="http://jythonet.appspot.com">jythonet</a>作者的一封邮件，受到启发，我打算扩展一下gefr这个WSGI adapter。原本gefr是写给soldat用来测试的，结果发现现在出现了买椟还珠的效果，既然大家更加关注这个，我决定多花一些时间在上面。不过话说回来gefr确实是Jython Web程序的新思路，过去大家都在想怎样把Jython放进Servlet中，gefr的思路是把Java的服务器实现放到WSGI后面。未来会有gefr-netty, gefr-mina, gefr-servlet等等出现，如果真的存在一个可靠的backend，也许这种思路也不失为一个办法，毕竟python的web框架更吸引人，而java的基础设施相对可靠，各取所长。</p>
<p>根据这个目的，现在gefr 0.2的API更新为：<br />
<script src="https://bitbucket.org/sunng/gefr/src/8490748055f1/src/examples/example.py?embed=t"></script></p>
<p>即在创建Gefr的时候需要告知backend类型，目前还只有soldat一种后端。未来也可能通过自动检测让这个参数成为可选。</p>
<p>gefr 0.2已经在开发中，您可以通过这里关注：<br />
<a href="https://bitbucket.org/sunng/gefr/overview">https://bitbucket.org/sunng/gefr/overview</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/03/gefr-api-updates/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Setting up soldat and gefr</title>
		<link>http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/</link>
		<comments>http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 08:40:23 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jip]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[soldat]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=813</guid>
		<description><![CDATA[本文介绍soldat服务器和gefr WSGI适配器的环境搭建，以及jip的基本使用。 安装python工具 virtualenv和pip是python开发的关键工具 sudo apt-get install python-virtualenv sudo apt-get install python-pip jython需要您手动下载安装。推荐安装到/usr/local/下，并建立软连接到/usr/local/bin/中，下文将假设您是这么做的。 创建虚拟jython环境 virtualenv -p /usr/local/bin/jython gefr-test cd gefr-test source bin/activate 安装jip pip install jip 配置jip 在$HOME下创建文件.jip，内容为： &#91;repos:oss&#93; uri=http://oss.sonatype.org/content/repositories/snapshots/ type=remote &#91;repos:central&#93; uri=http://repo1.maven.org/maven2/ type=remote &#91;repos:local&#93; uri=/home/sun/.m2/repository/ type=local 安装soldat 配置完jip后，可以使用jip来安装soldat jip &#8230; <a href="http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>本文介绍soldat服务器和gefr WSGI适配器的环境搭建，以及jip的基本使用。</p>
<h4>安装python工具</h4>
<p>virtualenv和pip是python开发的关键工具<br />
sudo apt-get install python-virtualenv<br />
sudo apt-get install python-pip</p>
<p>jython需要您手动下载安装。推荐安装到/usr/local/下，并建立软连接到/usr/local/bin/中，下文将假设您是这么做的。</p>
<h4>创建虚拟jython环境</h4>
<p>virtualenv -p /usr/local/bin/jython gefr-test<br />
cd gefr-test<br />
source bin/activate</p>
<h4>安装jip</h4>
<p>pip install jip</p>
<h4>配置jip</h4>
<p>在$HOME下创建文件.jip，内容为：</p>
<div class="codecolorer-container ini twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>repos:oss<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">http://oss.sonatype.org/content/repositories/snapshots/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">remote</span><br />
<br />
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>repos:central<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">http://repo1.maven.org/maven2/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">remote</span><br />
<br />
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>repos:local<span style="">&#93;</span></span><br />
<span style="color: #000099;">uri</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">/home/sun/.m2/repository/</span><br />
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">local</span></div></div>
<h4>安装soldat</h4>
<p>配置完jip后，可以使用jip来安装soldat<br />
jip install info.sunng.soldat:soldat:1.0-SNAPSHOT</p>
<p>文件将被下载到 javalib 目录中，您可以检查安装的正确性：<br />
$ ls javalib/<br />
log4j-1.2.16.jar     slf4j-log4j12-1.6.1.jar<br />
slf4j-api-1.6.1.jar  soldat-1.0-SNAPSHOT.jar</p>
<h4>安装gefr</h4>
<p>pip install gefr==0.1dev2</p>
<h4>创建一个简单的Python WSGI程序</h4>
<p>创建test.py</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> gefr <span style="color: #ff7700;font-weight:bold;">import</span> Gefr<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> wsgiapp<span style="color: black;">&#40;</span>environ<span style="color: #66cc66;">,</span> start_response<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; status <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'200 OK'</span><br />
&nbsp; &nbsp; res_body <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Welcome&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;It works!&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;&quot;</span><br />
&nbsp; &nbsp; res_headers <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Type'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'text/html'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Length'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>res_body<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; start_response<span style="color: black;">&#40;</span>status<span style="color: #66cc66;">,</span> res_headers<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>res_body<span style="color: black;">&#93;</span><br />
<br />
Gefr<span style="color: black;">&#40;</span>wsgiapp<span style="color: #66cc66;">,</span> host<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'0.0.0.0'</span><span style="color: #66cc66;">,</span> port<span style="color: #66cc66;">=</span><span style="color: #ff4500;">8000</span><span style="color: black;">&#41;</span>.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<h4>启动服务</h4>
<p>使用jip附带的jython-all<br />
jython-all test.py</p>
<p>打开浏览器，访问 http://localhost:8000/</p>
<h4>用ab测试服务性能</h4>
<p>$ ab -n 10000 -c 100 http://localhost:8000/</p>
<pre>
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests

Server Software:        gefr/0.1dev
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        79 bytes

Concurrency Level:      100
Time taken for tests:   2.539 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1640000 bytes
HTML transferred:       790000 bytes
Requests per second:    3938.11 [#/sec] (mean)
Time per request:       25.393 [ms] (mean)
Time per request:       0.254 [ms] (mean, across all concurrent requests)
Transfer rate:          630.71 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.6      0       8
Processing:     9   25  22.4     21     239
Waiting:        9   25  22.4     21     239
Total:         13   25  22.3     21     239

Percentage of the requests served within a certain time (ms)
  50%     21
  66%     22
  75%     22
  80%     23
  90%     26
  95%     40
  98%     65
  99%    233
 100%    239 (longest request)
</pre>
<p>Good Luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/03/setting-up-soldat-and-gefr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python3 script to query free TOEFL seats</title>
		<link>http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/</link>
		<comments>http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 14:46:19 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/</guid>
		<description><![CDATA[应同学要求，写了一个爬托福考试空闲考位的脚本。这是第一次真正用Python3写。 通过调用get_seat_status，传入省名（如&#8217;Jiangsu&#8217;），时间（如&#8217;201104&#8242;），您可以得到这样的数据结构： &#91; &#91;datetime.datetime&#40;2011, 4, 23, 10, 0&#41;, &#160;'STN80085B', &#160;'南通市教育装备与勤工俭学管理中心', &#160;'1415', &#160;True&#93;, &#160;&#91;datetime.datetime&#40;2011, 4, 23, 10, 0&#41;, 'STN80086A', '扬州大学', '1415', True&#93;&#93; 下面是一个多线程调用的例子： #! /usr/bin/python3 import threading import pprint from toeflgraber import get_seat_status # 查询江浙沪 2011年3月和4月的考位 locations = &#91;'Jiangsu', 'Shanghai', 'Zhejiang'&#93; &#8230; <a href="http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>应同学要求，写了一个爬托福考试空闲考位的脚本。这是第一次真正用Python3写。</p>
<p><script src="https://gist.github.com/846150.js?file=gistfile1.py"></script></p>
<p>通过调用get_seat_status，传入省名（如&#8217;Jiangsu&#8217;），时间（如&#8217;201104&#8242;），您可以得到这样的数据结构：</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: black;">&#91;</span> <span style="color: black;">&#91;</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">23</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #483d8b;">'STN80085B'</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #483d8b;">'南通市教育装备与勤工俭学管理中心'</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #483d8b;">'1415'</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #008000;">True</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp;<span style="color: black;">&#91;</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">23</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'STN80086A'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'扬州大学'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'1415'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></div></div>
<p>下面是一个多线程调用的例子：</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#! /usr/bin/python3</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">threading</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pprint</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> toeflgraber <span style="color: #ff7700;font-weight:bold;">import</span> get_seat_status<br />
<br />
<span style="color: #808080; font-style: italic;"># 查询江浙沪 2011年3月和4月的考位</span><br />
locations <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'Jiangsu'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Shanghai'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Zhejiang'</span><span style="color: black;">&#93;</span><br />
months <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'201103'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'201104'</span><span style="color: black;">&#93;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> descartes<span style="color: black;">&#40;</span>x<span style="color: #66cc66;">,</span> y<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> x:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> j <span style="color: #ff7700;font-weight:bold;">in</span> y:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: black;">&#40;</span>i<span style="color: #66cc66;">,</span> j<span style="color: black;">&#41;</span><br />
<br />
lock <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">RLock</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
tasks <span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>locations<span style="color: black;">&#41;</span> * <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>months<span style="color: black;">&#41;</span><br />
e <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Event</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
results <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> task<span style="color: black;">&#40;</span>location<span style="color: #66cc66;">,</span> month<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">global</span> results<span style="color: #66cc66;">,</span> tasks<br />
&nbsp; &nbsp; all_seats <span style="color: #66cc66;">=</span> get_seat_status<span style="color: black;">&#40;</span>location<span style="color: #66cc66;">,</span> month<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; available_seats <span style="color: #66cc66;">=</span> <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x<span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> all_seats<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">with</span> lock:<br />
&nbsp; &nbsp; &nbsp; &nbsp; results.<span style="color: black;">extend</span><span style="color: black;">&#40;</span>available_seats<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tasks -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> tasks <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> descartes<span style="color: black;">&#40;</span>locations<span style="color: #66cc66;">,</span> months<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; t <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span><span style="color: black;">&#40;</span>target<span style="color: #66cc66;">=</span>task<span style="color: #66cc66;">,</span> args<span style="color: #66cc66;">=</span>t<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; t.<span style="color: black;">daemon</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span><br />
&nbsp; &nbsp; t.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
e.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: #dc143c;">pprint</span>.<span style="color: #dc143c;">pprint</span><span style="color: black;">&#40;</span>results<span style="color: black;">&#41;</span></div></div>
<p>Enjoy it.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/02/python3-script-to-query-free-toefl-seats/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>包管理与路径管理</title>
		<link>http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/</link>
		<comments>http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/#comments</comments>
		<pubDate>Sat, 22 Jan 2011 08:07:17 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/</guid>
		<description><![CDATA[现在几乎每一种语言都有一些依赖管理工具，或者是中央的包仓库。比如这些： Java: maven, ivy, gradle Ruby: gems Python: easy_install, pip Clojure: leinigen Groovy: maven, grape, gradle Hashkell: cabal PHP: pear Nodejs: npm 这些工具在管理包和路径时都会采用各不相同的策略，有的是通过自身实现，有的是借助语言平台本身的特点。 Java 其中最注明的Maven，它的方式是在POM文件中定义你的依赖，Maven会在本地仓库中维护这些依赖。Maven的本地仓库默认是在$HOME/.m2/repository目录下，是用户独立的，当然要下载一个依赖也不需要root权限。而在通过Maven运行Java项目时，Maven插件会自动管理classpath，你并不需要把这些依赖从本地仓库里拷贝出来而单独维护一个所谓lib目录（这样也不好管理）。这是Maven的方式，目前看来，这也是最经典的一种方式。除了maven本身的特性以外，这也和Java的classpath机制有关。 最近势头很猛的Java构建工具gradle，方式也与Maven类似，它会把下载的依赖存放在$HOME/.gradle/cache目录里，并自动管理classpath。 同样是Java，与maven相对应的是ant+ivy。ivy可以为你管理依赖，但是ivy不会帮你管理classpath。ivy的包管理，是以project为scope的，你需要维护一个lib目录来存放这些下载的包，再通过传统的ant的方式去管理classpath，从而使项目可以进行编译和运行。 在Java世界里，还有一个特别的工具叫做grape，它是专门用于groovy的轻量级的依赖解决方案。grape是以脚本为scope，在需要依赖的脚本中通过@Grab声明依赖，grape工具可以从maven仓库中下载依赖到$HOME/.groovy/grapes中，并把相关的依赖加入groovy的classpath。除此以外，grape还有一个命令行工具帮助你手动下载依赖到本地仓库。grape的内部是基于ivy的，不过它的方式比ant要自动化很多。 在Java世界里还有一个特例，是Clojure的依赖管理工具leiningen。leiningen本身也比较简单，它的方式与ivy相同，会解析project.clj文件中定义的依赖关系，并下载到当前的工程目录下的lib中。lein是鼓励通过uberjar的方式把依赖统统打包的，所以它并没有classpath的管理功能。 总体来说，Java世界的工具和Java是相似的，其最大特点就是System independent，安装包不需要root权限，每次的运行都需要管理classpath。作为开发人员，classpath中有哪些可以访问的类库是可以控制的，这也使Java程序的移植性得到良好的控制和管理。 Python 与Java不同，Python通常作为系统分发的一部分，他的包管理和PATH管理要相对混乱一些。通常我们有两种方式来安装一个Python的软件包： sudo apt-get install python-redis sudo easy_install redis &#8230; <a href="http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>现在几乎每一种语言都有一些依赖管理工具，或者是中央的包仓库。比如这些：</p>
<ul>
<li>Java: maven, ivy, gradle</li>
<li>Ruby: gems</li>
<li>Python: easy_install, pip</li>
<li>Clojure: leinigen</li>
<li>Groovy: maven, grape, gradle</li>
<li>Hashkell: cabal</li>
<li>PHP: pear</li>
<li>Nodejs: npm</li>
</ul>
<p>这些工具在管理包和路径时都会采用各不相同的策略，有的是通过自身实现，有的是借助语言平台本身的特点。</p>
<h3>Java</h3>
<p>其中最注明的Maven，它的方式是在POM文件中定义你的依赖，Maven会在本地仓库中维护这些依赖。Maven的本地仓库默认是在$HOME/.m2/repository目录下，是用户独立的，当然要下载一个依赖也不需要root权限。而在通过Maven运行Java项目时，Maven插件会自动管理classpath，你并不需要把这些依赖从本地仓库里拷贝出来而单独维护一个所谓lib目录（这样也不好管理）。这是Maven的方式，目前看来，这也是最经典的一种方式。除了maven本身的特性以外，这也和Java的classpath机制有关。</p>
<p>最近势头很猛的Java构建工具gradle，方式也与Maven类似，它会把下载的依赖存放在$HOME/.gradle/cache目录里，并自动管理classpath。</p>
<p>同样是Java，与maven相对应的是ant+ivy。ivy可以为你管理依赖，但是ivy不会帮你管理classpath。ivy的包管理，是以project为scope的，你需要维护一个lib目录来存放这些下载的包，再通过传统的ant的方式去管理classpath，从而使项目可以进行编译和运行。</p>
<p>在Java世界里，还有一个特别的工具叫做grape，它是专门用于groovy的轻量级的依赖解决方案。grape是以脚本为scope，在需要依赖的脚本中通过@Grab声明依赖，grape工具可以从maven仓库中下载依赖到$HOME/.groovy/grapes中，并把相关的依赖加入groovy的classpath。除此以外，grape还有一个命令行工具帮助你手动下载依赖到本地仓库。grape的内部是基于ivy的，不过它的方式比ant要自动化很多。</p>
<p>在Java世界里还有一个特例，是Clojure的依赖管理工具leiningen。leiningen本身也比较简单，它的方式与ivy相同，会解析project.clj文件中定义的依赖关系，并下载到当前的工程目录下的lib中。lein是鼓励通过uberjar的方式把依赖统统打包的，所以它并没有classpath的管理功能。</p>
<p>总体来说，Java世界的工具和Java是相似的，其最大特点就是System independent，安装包不需要root权限，每次的运行都需要管理classpath。作为开发人员，classpath中有哪些可以访问的类库是可以控制的，这也使Java程序的移植性得到良好的控制和管理。</p>
<h3>Python</h3>
<p>与Java不同，Python通常作为系统分发的一部分，他的包管理和PATH管理要相对混乱一些。通常我们有两种方式来安装一个Python的软件包：</p>
<ul>
<li>sudo apt-get install python-redis</li>
<li>sudo easy_install redis</li>
</ul>
<p>一种是通过系统的包管理工具（如apt-get）从系统的软件仓库里安装，一种是通过python自己的包管理工具（如easy_install / pip）从Python Cheese Shop中下载安装。这两种安装方式有什么不同呢。以Ubuntu为例，通过apt-get安装的python包通常会被放在 /usr/share/pyshared 或 /usr/lib/python2.6/dist-packages 中，相对应的，由easy_install安装的Python包，则存放在 /usr/local/lib/python2.6/dist-packages 中。Python启动后可以通过查看sys.path来了解当前的path情况。</p>
<p>除了安装到系统目录，easy_install可以通过 &#8211;user 选项来把软件包安装到用户目录 $HOME/.local/lib/python2.6/site-packages。不过无论是系统级别还是用户级别，python都很难在启动时管理Path，即任何时候python都可以访问安装在系统中的所有软件包。这导致了混乱的情况，导致编写的python软件难以进行依赖管理和移植（即使没有定义在setup.py中，很多依赖还是可以访问的）。</p>
<p>由此virtualenv营运而生，virtualenv帮助你创建一个独立的python运行环境。激活这个小环境之后，easy_install/pip仅仅安装软件到小环境，python仅能访问环境内部的site-packages，这样整个环境中的依赖关系就非常清楚，也保障了程序的移植性。这样，就将原本系统scope的python包管理级别改进为项目级别。我之前写的jip也是将依赖下载或拷贝到virtualenv的小环境中，并且修改jython的启动脚本修改PYTHONPATH的设置，保证Java依赖对Jython的透明可访问。</p>
<h3>Nodejs</h3>
<p>nodejs是一个新兴的生态系统，一个包管理工具对其也是必不可少。npm是目前整个社区都比较认可的工具。</p>
<p>不过目前npm并不好用。npm默认会把自己安装到 node安装前缀的目录，比如node安装时你选择了默认前缀/usr/local，那么npm会把自己安装到/usr/local/lib/node里。这个目录是系统级别的，所以需要root权限，而npm本身又不鼓励用户用root权限来安装软件包（安全问题）。所以作者说希望用户把/usr/local/lib/node权限授予用户，或者把node安装到用户目录里。这两种方式其实都不太优雅。</p>
<p>Ruby的gems在这方面最符合unix哲学，即用户知道自己在做什么。如果用户以root权限运行gem  install，gem会把软件包安装到系统目录中对所有用户可用，而如果以普通用户权限运行，则安装到用户目录 $HOME/.gem 中仅当前用户可见。</p>
<p>nodejs在加载软件包时，会在require.paths中的几个目录里查找，前两个都是用户目录，所以npm也并非一定要把包安装到系统目录里去。虽然现在可以用过修改.npmrc文件在修改npm的默认行为，不过在这个CoC的时代，显然太繁琐了。</p>
<h3>Best Pratice</h3>
<p>总结一下，包管理和路径管理的最佳实践应该是：语言平台有CoC的路径机制，包管理器有基于环境变量、用户权限的判断执行合适行为。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/01/%e5%8c%85%e7%ae%a1%e7%90%86%e4%b8%8e%e8%b7%af%e5%be%84%e7%ae%a1%e7%90%86/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>soldat &amp; gefr</title>
		<link>http://sunng.info/blog/2011/01/soldat-gefr/</link>
		<comments>http://sunng.info/blog/2011/01/soldat-gefr/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 16:31:09 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[gefr]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jython]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[soldat]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/2011/01/soldat-gefr/</guid>
		<description><![CDATA[我的这一套stack正在走向完整。上次贴了一张soldat-http的图，现在基于soldat的wsgi服务器也已经有了一个基本可以运行的实现，名字叫做gefr（我的命名出处参考这里）。现在gefr上已经可以跑基于bottle框架的wsgi程序了，也就是说一些基于python的web应用可能可以通过jython来运行在soldat上。为了搞定jython的环境，这几天我还花了不少时间做了jip帮我从maven仓库里自动下载依赖的jar包。 soldat和gefr的代码都放在我的bitbucket上： soldat https://bitbucket.org/sunng/soldat gefr https://bitbucket.org/sunng/gefr 此外，这两个项目也分别发布到了sonatype oss仓库和python cheese shop。 现在还有几个问题： soldat在读buffer的时候先获得buffer的limit，再去读相应长度的buffer有时会出现BufferUnderflowException。这个可能存在线程安全问题，现在还没发现。 gefr启动之后可以通过在jvisualvm里找到这个进程，但是绑定profiler之后很诡异的是gefr就不再处理请求了。 直接用soldat的处理http请求，吞吐量可以上万；但是在上面加上jython的gefr，再加上bottle框架，同样的功能吞吐量就剩下原来的十分之一了。就是因为没法做profile，所以还不知道时间花到哪里去了。 简单地 announce 一下，这样我有更多的动力来继续把这两个小东西做好。]]></description>
			<content:encoded><![CDATA[<p>我的这一套stack正在走向完整。上次贴了一张soldat-http的图，现在基于soldat的wsgi服务器也已经有了一个基本可以运行的实现，名字叫做gefr（我的命名出处参考<a href="http://en.wikipedia.org/wiki/Rank_insignia_of_the_German_armed_forces">这里</a>）。现在gefr上已经可以跑基于bottle框架的wsgi程序了，也就是说一些基于python的web应用可能可以通过jython来运行在soldat上。为了搞定jython的环境，这几天我还花了不少时间做了jip帮我从maven仓库里自动下载依赖的jar包。</p>
<p>soldat和gefr的代码都放在我的bitbucket上：</p>
<ul>
<li>soldat <a href="https://bitbucket.org/sunng/soldat">https://bitbucket.org/sunng/soldat</a></li>
<li>gefr <a href="https://bitbucket.org/sunng/gefr">https://bitbucket.org/sunng/gefr</a></li>
</ul>
<p>此外，这两个项目也分别发布到了<a href="https://oss.sonatype.org/content/repositories/snapshots/">sonatype oss仓库</a>和<a href="http://pypi.python.org/pypi/gefr">python cheese shop</a>。</p>
<p>现在还有几个问题：</p>
<ul>
<li>soldat在读buffer的时候先获得buffer的limit，再去读相应长度的buffer有时会出现BufferUnderflowException。这个可能存在线程安全问题，现在还没发现。</li>
<li>gefr启动之后可以通过在jvisualvm里找到这个进程，但是绑定profiler之后很诡异的是gefr就不再处理请求了。</li>
<li>直接用soldat的处理http请求，吞吐量可以上万；但是在上面加上jython的gefr，再加上bottle框架，同样的功能吞吐量就剩下原来的十分之一了。就是因为没法做profile，所以还不知道时间花到哪里去了。</li>
</ul>
<p>简单地 announce 一下，这样我有更多的动力来继续把这两个小东西做好。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/01/soldat-gefr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

