<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10japanesefull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ck4CSHk8fCp7ImA9WhVbE0s.&quot;"><id>tag:blogger.com,1999:blog-18400048</id><updated>2012-05-30T15:56:09.774+09:00</updated><category term="ruby" /><category term="dotcloud" /><category term="couchdb" /><category term="pyaaws" /><category term="templates" /><category term="technology" /><category term="postgresql" /><category term="ec2" /><category term="unittest" /><category term="pyinstaller" /><category term="redis" /><category term="jenkins" /><category term="perl" /><category term="social" /><category term="conference" /><category term="pyside" /><category term="application" /><category term="cheat" /><category term="chrome" /><category term="memcache" /><category term="delphi" /><category term="win32" /><category term="test" /><category term="raindrop" /><category term="py3k" /><category term="instagram" /><category term="iphone" /><category term="css" /><category term="shell" /><category term="python" /><category term="heartbeat" /><category term="py2app" /><category term="study" /><category term="nginx" /><category term="wsgi" /><category term="qt4" /><category term="ci" /><category term="todo" /><category term="bat" /><category term="windows" /><category term="vim" /><category term="code" /><category term="xhtml" /><category term="aws" /><category term="wave" /><category term="apache" /><category term="innosetup" /><category term="centos" /><category term="developper" /><category term="py2exe" /><category term="mysql" /><category term="java" /><category term="translation" /><category term="php" /><category term="rtm" /><category term="pyspa" /><category term="music" /><category term="algorithm" /><category term="game" /><category term="django" /><category term="mongodb" /><category term="gui" /><category term="googleapps" /><category term="pdf" /><category term="life" /><category term="pagination" /><category term="jquery" /><category term="trac" /><category term="pyqt" /><category term="gdd2009" /><category term="blogger" /><category term="topcoder" /><category term="reposearch" /><category term="twitter" /><category term="financial statements" /><category term="server" /><category term="design" /><category term="windows7" /><category term="gaware" /><category term="redmine" /><category term="ubuntu" /><category term="fukuoka" /><category term="mercurial" /><category term="WAF" /><category term="pypy" /><category term="googleappengine" /><category term="subversion" /><category term="google" /><category term="db" /><title type="text">Surgo</title><subtitle type="html">lazy programmer's blog.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://surgo.jp/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://surgo.jp/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>104</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/surgo/posts" /><feedburner:info uri="surgo/posts" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://paipo.jp/bookmarklet/?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.feedburner.jp/fb/i/subscribe_paipo.gif">Paipo???</feedburner:feedFlare><feedburner:feedFlare href="http://add.my.yahoo.co.jp/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://i.yimg.jp/i/jp/my/addtomy/standard_bb.gif">myyahoo???</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.newsgator.com/images/ngsub1.gif">NewsGator Online???</feedburner:feedFlare><feedburner:feedFlare href="http://feedpath.jp/feedreader/feeds_add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://feedpath.jp/common/images/sub_feedpath.gif">feedpath???</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/surgo/posts" src="http://www.bloglines.com/images/sub_modern11.gif">Bloglines???</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://buttons.googlesyndication.com/fusion/add.gif">Google???</feedburner:feedFlare><feedburner:feedFlare href="http://r.hatena.ne.jp/append/http://feeds.feedburner.com/surgo/posts" src="http://r.hatena.ne.jp/images/addto_w.gif">???RSS???</feedburner:feedFlare><feedburner:feedFlare href="http://reader.livedoor.com/subscribe/http://feeds.feedburner.com/surgo/posts" src="http://image.reader.livedoor.com/img/banner/91_17_1.gif">Livedoor???????</feedburner:feedFlare><feedburner:feedFlare href="http://reader.goo.ne.jp/web/bookmarklet.html?,,http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://reader.goo.ne.jp/web/img/addwebrss.gif">goo RSS???????</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fsurgo%2Fposts" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><entry gd:etag="W/&quot;DEMEQHg8cSp7ImA9WhVVF0w.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-1661881281286445252</id><published>2012-05-10T17:50:00.001+09:00</published><updated>2012-05-11T15:06:41.679+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-11T15:06:41.679+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ci" /><category scheme="http://www.blogger.com/atom/ns#" term="dotcloud" /><category scheme="http://www.blogger.com/atom/ns#" term="jenkins" /><title>Jenkins on dotCloud</title><content type="html">&lt;p&gt;前回書いた記事のアップデート。jetty をよく理解してなかった orz。シンプルに &lt;a href="https://www.dotcloud.com/" target="_blank" title="dotCloud"&gt;dotCloud&lt;/a&gt; に jenkins.war をデプロイするだけでいけますね。&lt;/p&gt; &lt;h4&gt;プロジェクト作成&lt;/h4&gt; &lt;p&gt;プロジェクト名を jenkins として作っています。&lt;/p&gt; 
&lt;pre&gt;
$ dotcloud create jenkins
$ mkdir jenkins
&lt;/pre&gt;
 &lt;p&gt;ディレクトリ階層は以下のように。jenkins.war は &lt;a href="http://jenkins-ci.org/" target="_blank" title="Jenkins"&gt;jenkins-co.org&lt;/a&gt; からダウンロード。&lt;/p&gt; 
&lt;pre&gt;
$ tree jenkins/
jenkins/
├── dotcloud.yml
└── webapps
    └── jenkins.war
&lt;/pre&gt;
 &lt;p&gt;dotcloud.yml の内容&lt;/p&gt; 
&lt;pre&gt;
$ cat jenkins/dotcloud.yml
www:
  type: java
  approot: webapps
&lt;/pre&gt;
 &lt;p&gt;まんまデプロイ。&lt;/p&gt; 
&lt;pre&gt;
$ dotcloud push jenkins jenkins/
&lt;/pre&gt;
 &lt;h4&gt;jetty@dotCloud の設定&lt;/h4&gt; &lt;p&gt;こっからは dotCloud のインスタンスに ssh アクセスして設定&lt;/p&gt; &lt;p&gt;(更新: user.home ごと書き換える)&lt;/p&gt; 
&lt;pre&gt;
$ dotcloud ssh jenkins.www  # ssh でアクセス
&lt;/pre&gt;
 &lt;p&gt;ワークスペースを作成する。&lt;/p&gt; 
&lt;pre&gt;
$ mkdir jenkins
$ chmod g+w jenkins
&lt;/pre&gt;
 &lt;p&gt;後は、&lt;a href="http://docs.codehaus.org/display/JETTY/ContextDeployer" target="_blank" title="ContextDeployer"&gt;jetty の設定&lt;/a&gt;。&lt;code&gt;~/contexts/&lt;/code&gt; ディレクトリ以下に、以下のような xml を追加。名前は何でもいいけど、とりあえず &lt;code&gt;contexts/jenkins.xml&lt;/code&gt; など。書いたのは、パスの設定と &lt;code&gt;JENKINS_HOME&lt;/code&gt; の設定だけ。ここで設定するので、&lt;a href="http://docs.dotcloud.com/services/java/" target="_blank" title="dotCloud - Java"&gt;ROOT.war&lt;/a&gt; とかに変更する必要もなし。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
  "http://jetty.mortbay.org/configure.dtd"&amp;gt;
&amp;lt;Configure class="org.mortbay.jetty.webapp.WebAppContext"&amp;gt;
  &amp;lt;Set name="contextPath"&amp;gt;/&amp;lt;/Set&amp;gt;
  &amp;lt;Set name="war"&amp;gt;&amp;lt;SystemProperty name="jetty.home" default="."/&amp;gt;/webapps/jenkins.war&amp;lt;/Set&amp;gt;
  &amp;lt;Call class="java.lang.System" name="setProperty"&amp;gt;
    &amp;lt;Arg&amp;gt;JENKINS_HOME&amp;lt;/Arg&amp;gt;
    &amp;lt;Arg&amp;gt;/home/dotcloud/jenkins&amp;lt;/Arg&amp;gt;
  &amp;lt;/Call&amp;gt;
&amp;lt;/Configure&amp;gt;
&lt;/pre&gt;
 &lt;p&gt;(追記) もしくは &lt;code&gt;user.home&lt;/code&gt; ごと設定する。この場合、ワークスペースが &lt;code&gt;/home/dotcloud/.jenkins&lt;/code&gt; になるので注意。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
  "http://jetty.mortbay.org/configure.dtd"&amp;gt;
&amp;lt;Configure class="org.mortbay.jetty.webapp.WebAppContext"&amp;gt;
  &amp;lt;Set name="contextPath"&amp;gt;/&amp;lt;/Set&amp;gt;
  &amp;lt;Set name="war"&amp;gt;&amp;lt;SystemProperty name="jetty.home" default="."/&amp;gt;/webapps/jenkins.war&amp;lt;/Set&amp;gt;
  &amp;lt;Call class="java.lang.System" name="setProperty"&amp;gt;
    &amp;lt;Arg&amp;gt;user.home&amp;lt;/Arg&amp;gt;
    &amp;lt;Arg&amp;gt;/home/dotcloud&amp;lt;/Arg&amp;gt;
  &amp;lt;/Call&amp;gt;
&amp;lt;/Configure&amp;gt;
&lt;/pre&gt;
 &lt;p&gt;なぜかデプロイの度に &lt;code&gt;contexts/jenkins.xml&lt;/code&gt; が消える。。。まーいいや。レッツ CI。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-1661881281286445252?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/p6rD7v_AZRpuHkHmgXMDc922KOc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/p6rD7v_AZRpuHkHmgXMDc922KOc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/p6rD7v_AZRpuHkHmgXMDc922KOc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/p6rD7v_AZRpuHkHmgXMDc922KOc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=kiJomG-vByY:Q7b0ON6G1zM:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=kiJomG-vByY:Q7b0ON6G1zM:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/kiJomG-vByY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/1661881281286445252/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2012/05/jenkins-on-dotcloud.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/1661881281286445252?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/1661881281286445252?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/kiJomG-vByY/jenkins-on-dotcloud.html" title="Jenkins on dotCloud" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2012/05/jenkins-on-dotcloud.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYMRXw9cCp7ImA9WhVWGEk.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-7238227254362774520</id><published>2012-05-01T12:04:00.001+09:00</published><updated>2012-05-01T13:39:44.268+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-01T13:39:44.268+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="shell" /><title>Secure Shell - Awesome extention for Chrome</title><content type="html">これはすごい！Windows でも使える素敵なタブ機能付き Shell クライアントががが！Chrome extention です。10h/24h 以上は secure shell の中で生活しているので、これで捗ります。&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/pnhechapfaindjhompbnflcldabbghjo" target="_blank" title="Secure Shell"&gt;Chrome Web Store - Secure Shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://git.chromium.org/gitweb/?p=chromiumos/platform/assets.git;a=blob;f=chromeapps/hterm/doc/faq.txt" target="_blank" title="FAQ"&gt;FAQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://groups.google.com/a/chromium.org/group/chromium-hterm/topics" target="_blank" title="chromium-hterm"&gt;Google Group&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
chromiumos 用に開発されてるようですね。動作もサクサクですし、今のところなんの問題もなく動作してます。現在 beta 版で公開鍵認証等はサポートされていませんが、恐らくすぐに&lt;a href="https://groups.google.com/a/chromium.org/group/chromium-hterm/browse_thread/thread/3779d3c50bb2586e/1ccc6c2f0b22fe11#1ccc6c2f0b22fe11" target="_blank" title="Support for public key authentication"&gt;サポート&lt;/a&gt;されると思います。&lt;br /&gt;
&lt;h3&gt;

# スクリーンショット&lt;/h3&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-_keXFKDizjE/T59S-hOuskI/AAAAAAAAItA/9V9jgUqoDVA/s1600/screen01.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="244" src="http://1.bp.blogspot.com/-_keXFKDizjE/T59S-hOuskI/AAAAAAAAItA/9V9jgUqoDVA/s320/screen01.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;接続画面 マルチバイトも問題なく表示&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-zlzFAS4m8Ew/T59TBM9TaQI/AAAAAAAAItI/_UdQjirQtVM/s1600/screen02.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="244" src="http://1.bp.blogspot.com/-zlzFAS4m8Ew/T59TBM9TaQI/AAAAAAAAItI/_UdQjirQtVM/s320/screen02.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Vim もサクサク&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;

# ブックマーク&lt;/h3&gt;
以下の URL でブックマークができます&lt;br /&gt;
&lt;code&gt;chrome-extension://pnhechapfaindjhompbnflcldabbghjo/html/nassh.html#&lt;/code&gt;&lt;i&gt;user&lt;/i&gt;&lt;code&gt;@&lt;/code&gt;&lt;i&gt;host&lt;/i&gt;&lt;code&gt;:&lt;/code&gt; &lt;i&gt;port&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-7238227254362774520?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/v1iF6SX3dABGKEKwdKE9tU1UZz8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/v1iF6SX3dABGKEKwdKE9tU1UZz8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/v1iF6SX3dABGKEKwdKE9tU1UZz8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/v1iF6SX3dABGKEKwdKE9tU1UZz8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=B46J7U54weE:4Yisx-Sb_wQ:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=B46J7U54weE:4Yisx-Sb_wQ:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/B46J7U54weE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/7238227254362774520/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2012/05/secure-shell-awesome-extention-for.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7238227254362774520?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7238227254362774520?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/B46J7U54weE/secure-shell-awesome-extention-for.html" title="Secure Shell - Awesome extention for Chrome" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-_keXFKDizjE/T59S-hOuskI/AAAAAAAAItA/9V9jgUqoDVA/s72-c/screen01.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2012/05/secure-shell-awesome-extention-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcMSXY6fCp7ImA9WhVWE0g.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-6466302669790060837</id><published>2012-04-25T21:48:00.001+09:00</published><updated>2012-04-25T21:48:08.814+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-25T21:48:08.814+09:00</app:edited><title>Windows 8 - Windows Developer Days</title><content type="html">&lt;a href="https://twitter.com/#!/ats" target="_blank"&gt;@ats&lt;/a&gt; 先生のご紹介で &lt;a href="http://www.microsoft.com/ja-jp/events/wdd/default.aspx" target="_blank"&gt;Windows Developer Days&lt;/a&gt; に参加させて頂きました。ありがとうございます！Microsoft のイベントは 10 年振りぐらいですかね。前回行ったパシフィコ横浜の時に比べると、こじんまりした会場で、人口密度がかなり高く、装飾が派手でした。Windows 8 は他の OS に負けない UI ! という意気込みを感じます。&lt;br /&gt;
セッションもメトロスタイルなアプリのデザイニングに関するものが厚めでした。MS 社のイベントでこれだけデザインの話がでるというのも新鮮です。今んとこ開発予定はないですが、メモ&lt;br /&gt;
&lt;h4&gt;



Windows 8&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;RC 版を 6 月 1 週にリリース&lt;/li&gt;
&lt;li&gt;スタートボタンから Metro UI へ (デスクトップモードもちゃんとある)&lt;/li&gt;
&lt;li&gt;USB で持ち歩ける -&amp;gt; Windows To Go (抜いたら停止、挿したら再開、抜いて 60s 経ったらシャットダウンし、データも消える)&lt;/li&gt;
&lt;li&gt;新しく Metro スタイルアプリが追加&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-GadlLfXoU9Q/T5fuWeUmn7I/AAAAAAAAInE/hgb5XKAltuk/s1600/windows-8-platform-and-tools.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="180" src="http://3.bp.blogspot.com/-GadlLfXoU9Q/T5fuWeUmn7I/AAAAAAAAInE/hgb5XKAltuk/s320/windows-8-platform-and-tools.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h4&gt;



Metro style Apps&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;MVC は HTML/CSS/JavaScript or silverlight で&lt;/li&gt;
&lt;li&gt;ネイティブリソースにアクセスする場合は WinRT or WinJS&lt;/li&gt;
&lt;li&gt;MS の方曰く、IE で動くものは基本的に移植可能&lt;/li&gt;
&lt;li&gt;白石先生 (html5j.org) 曰く、html5 アプリがそのまま動けばいいけど、制限があるため Metro アプリケーション用に改修が必要とのこと&lt;br /&gt;※ iframe なら可&lt;/li&gt;
&lt;li&gt;配布は基本的に Windows Store のみ&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/library/windows/apps/hh779072.aspx" target="_blank"&gt;デザインガイド&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;



その他&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Hadoop の Windows ディストリを公開予定&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Hive や Pig 等の主要プラグインもパッケージング&lt;/li&gt;
&lt;li&gt;Server 版と Azure 版を提供予定 (Azure 先行)&lt;/li&gt;
&lt;li&gt;すべて javascript で制御可能&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/windowsazure/hh531535" target="_blank"&gt;rails アプリケーションを Azure で動かす&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Intel Ivy bridge は省電力とのこと&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Intel の&amp;nbsp;&lt;a href="http://www.intel.com/content/www/us/en/silicon-innovations/intel-tick-tock-model-general.html" target="_blank"&gt;Tick-Tock&lt;/a&gt;&amp;nbsp;戦略の Tock&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;a href="http://software.intel.com/en-us/intel-sdp-home/" target="_blank"&gt;Intel Parallel Studio&lt;/a&gt; は面白かった！&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;パフォーマンス分析、チューニングが出来る&lt;/li&gt;
&lt;li&gt;プロファイルとか最適化されてるかがかなりリアルタイムで見れる&lt;/li&gt;
&lt;li&gt;バイトコードまで追える&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
最後に。それ Python でできるよ！&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-6466302669790060837?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cESXD_2rNEfTg-w1fvQGwexyhds/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cESXD_2rNEfTg-w1fvQGwexyhds/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cESXD_2rNEfTg-w1fvQGwexyhds/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cESXD_2rNEfTg-w1fvQGwexyhds/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=h_hIU7eMoZs:vWjVs55l2g0:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=h_hIU7eMoZs:vWjVs55l2g0:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/h_hIU7eMoZs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/6466302669790060837/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2012/04/windows-8-windows-developer-days.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/6466302669790060837?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/6466302669790060837?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/h_hIU7eMoZs/windows-8-windows-developer-days.html" title="Windows 8 - Windows Developer Days" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-GadlLfXoU9Q/T5fuWeUmn7I/AAAAAAAAInE/hgb5XKAltuk/s72-c/windows-8-platform-and-tools.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2012/04/windows-8-windows-developer-days.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMCQn86cCp7ImA9WhVWEU0.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-2776955498223515107</id><published>2012-04-22T22:47:00.001+09:00</published><updated>2012-04-22T22:47:43.118+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-22T22:47:43.118+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="qt4" /><category scheme="http://www.blogger.com/atom/ns#" term="pyside" /><category scheme="http://www.blogger.com/atom/ns#" term="pyqt" /><title>実践 Qt4 プログラミング - O'Reilly</title><content type="html">&lt;p&gt;O'Reilly 様から "&lt;a href="http://www.oreilly.co.jp/books/9784873115078/" target="_blank" title="実践 Qt 4プログラミング"&gt;実践 Qt4 プログラミング&lt;/a&gt;" をご献本頂きました。&lt;strong&gt;有難うございます&lt;/strong&gt;！！初めての献本ということで小躍りしました。この本は入門書ではないので、今から Qt4 を触りたいという方は "&lt;a href="http://www.oreilly.co.jp/books/9784873113449/" target="_blank" title="入門 Qt 4プログラミング"&gt;入門 Qt4プログラミング&lt;/a&gt; - O'Reilly" もあります。&lt;/p&gt; &lt;p&gt;中身をどこまで書いていいのかわかりませんが (w、各章で Web アプリケーションクライアント、メディアプレイヤー、データ・モデルビュアー、エディタ等々&lt;span style="TEXT-DECORATION: underline"&gt;幅広い&lt;/span&gt;デスクトップアプリについて解説されています。データ・モデルビュアーが厚めです。その各章にアプリケーションの作例 (25 ちょい) があり、&lt;span style="TEXT-DECORATION: underline"&gt;丁寧にコードリーディングしていくことができます&lt;/span&gt;。サンプルコード量約 2 万行w 読み応え十二分です。Qt は (この本がカバーしてる &lt;span style="TEXT-DECORATION: underline"&gt;Ver.4.6&lt;/span&gt;) &lt;a href="http://doc.qt.nokia.com/4.6/classes.html" target="_blank" title="All Qt Classes"&gt;800 近いクラス&lt;/a&gt;からなっているので、そんなもんなんでしょうね。&lt;/p&gt; &lt;p&gt;クラスの API リファレンスは公式ドキュメントを読むとして、この本の素敵なところはコードリーディングをしていくうちに &lt;span style="TEXT-DECORATION: underline"&gt;Qt4 の重要な機能を理解できる&lt;/span&gt;ことと、&lt;span style="TEXT-DECORATION: underline"&gt;デスクトップアプリケーションを作る際に気を付けるべきことが勉強できる&lt;/span&gt;ことだと思いました。まさに実践向きですね。あと、プラットフォームごとの差異、非推奨の機能、デスクトップアプリを作成する際に注意すべきことが各所で紹介されています。これも嬉しいですね。クロスプラットフォームなデスクトップアプリにご興味がある方は必読だと思います。&lt;/p&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; PySide/PyQt の参考書としては?&lt;/p&gt; &lt;p&gt;&lt;span style="TEXT-DECORATION: underline"&gt;十分使えます&lt;/span&gt;。量バインディング共によく出来ていて、クラス名やプロパティはそのまま、c++ で書かれているロジックを Python に置き換えれば動きます。ただし、マクロは Python に書き換える必要があるのと、シグナル・スロットの書き方、各クラスが属しているモジュール (QtCore, QtCore.Qt, QtGui...) は調べる必要があります。&lt;/p&gt; &lt;p&gt;アプリケーションを起動する main 関数&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setApplicationName(app.translate("main", "Application name"));
    ...

    FooWidget foo;
    foo.show();

    return app.exec();
}
&lt;/pre&gt;
 
&lt;pre class="prettyprint"&gt;
import sys
from PySide import QtGui


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    app.setApplicationName(app.tr('Application name'))
    ...

    foo = FooWidget()
    foo.show()

    app.exec_()
    sys.exit()
&lt;/pre&gt;
 &lt;p&gt;マクロ&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
#ifdef Q_WS_MAC
    // For mac
#endif
&lt;/pre&gt;
 
&lt;pre class="prettyprint"&gt;
import sys


if sys.platform == 'darwin':
    # For mac
&lt;/pre&gt;
 &lt;p&gt;O'Reilly 様からお許しもらえたら、各アプリを PySide で解説させていただきたいです！&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-2776955498223515107?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4yIaJcVtE_tyduE_txya-Q14X_o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4yIaJcVtE_tyduE_txya-Q14X_o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4yIaJcVtE_tyduE_txya-Q14X_o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4yIaJcVtE_tyduE_txya-Q14X_o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=nJ0l6NixSdY:WLEb9olEx-8:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=nJ0l6NixSdY:WLEb9olEx-8:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/nJ0l6NixSdY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/2776955498223515107/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2012/04/qt4-o.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/2776955498223515107?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/2776955498223515107?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/nJ0l6NixSdY/qt4-o.html" title="実践 Qt4 プログラミング - O&amp;#39;Reilly" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2012/04/qt4-o.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMNSHg6eip7ImA9WhVXFkg.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-3814178044556937331</id><published>2012-04-17T16:41:00.001+09:00</published><updated>2012-04-17T18:54:59.612+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-17T18:54:59.612+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="server" /><category scheme="http://www.blogger.com/atom/ns#" term="django" /><category scheme="http://www.blogger.com/atom/ns#" term="mysql" /><category scheme="http://www.blogger.com/atom/ns#" term="nginx" /><category scheme="http://www.blogger.com/atom/ns#" term="redis" /><category scheme="http://www.blogger.com/atom/ns#" term="aws" /><category scheme="http://www.blogger.com/atom/ns#" term="db" /><title>Pinterest のスケール</title><content type="html">&lt;p&gt;&lt;a href="https://twitter.com/#!/voluntas/statuses/191883287935979520" target="_blank"&gt;V 先生から&lt;/a&gt;教えて頂いたので、Instagram 同様 Django/AWS 構成の Pinterest のスケールをメモ。&lt;del&gt;Pinterest はいつものアカウント名が初めて&lt;/del&gt; &lt;a href="http://pinterest.com/surgo/" target="_blank"&gt;&lt;del&gt;先取&lt;/del&gt;&lt;/a&gt; &lt;del&gt;されたサービスなので、今後使わないと思います&lt;/del&gt;。&lt;/p&gt; &lt;p&gt;本題に入る前に、Python には &lt;a href="http://www.python.org/dev/peps/pep-0020/" target="_blank" title="The Zen of Python"&gt;The Zen of Python&lt;/a&gt; (&lt;a href="http://www.python.jp/Zope/articles/misc/zen" target="_blank" title="The Zen of Python (日本語)"&gt;日本語&lt;/a&gt;) という思想があります。私はこの思想を Python でのプログラミングだけでなく、インフラの構築の際も意識するように心がけています。"&lt;span style="TEXT-DECORATION: underline"&gt;Simple is better than complex&lt;/span&gt;" です。Instagram や Pinterest のスケールを見て、この思想がもっと好きになりました。&lt;/p&gt; &lt;p&gt;Instagram はよりシンプルなインフラに更改していくことで、ただスケールするだけでなく、運用や変更のコストも最小限になるように最適化していると思います。結果的に Android アプリ公開等のサービス拡大時にも少ないエンジニアリングで柔軟に対応できたのかと。これはあくまでもイメージでしかありませんが、AWS 上でスケールアップできるところまでスケールアップし、限界が見えたところでスケールアウトで最小限のエンジニアリングコストをかける。インフラで解決できるところはインフラで解決しているというイメージです。Pinterest のスライドでは、インフラをシンプルに更改した過程が紹介されています。&lt;/p&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; インフラの遷移&lt;/p&gt; &lt;ul&gt; &lt;li&gt;2010/05: 創設&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.rackspace.com/" target="_blank" title="RackSpace"&gt;RackSpace&lt;/a&gt;&lt;/li&gt; &lt;li&gt;小規模な Web Engine × 1&lt;/li&gt; &lt;li&gt;小規模な MySQL DB × 1&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;2011/01: AWS へ &lt;br/&gt;フロントに nginx を立て垂直分割、MySQL をマスタースレーブ構成に垂直分割、ヘビーな処理をタスクキューに分割、MongoDB を導入。&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;Amazon EC2 + S3 + CloudFront&lt;/li&gt; &lt;li&gt;nginx × 1&lt;/li&gt; &lt;li&gt;Web Engine × 4&lt;/li&gt; &lt;li&gt;MySQL: Master × 1 / Slave × 1&lt;/li&gt; &lt;li&gt;Task Queue × 1 / Task Processors × 2&lt;/li&gt; &lt;li&gt;MongoDB × 1&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;2011 年後半: ターニングポイント &lt;br/&gt;LB, Web サーバを増加、MySQL をシャーディングにより水平分割、Cassandra, Membase, Redis 等の分散型KVS を導入、MongoDB をクラスタ化。&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;Amazon EC2 + S3 + CloudFront&lt;/li&gt; &lt;li&gt;nginx × 2&lt;/li&gt; &lt;li&gt;Web Engine × 16 / API Engine × 2&lt;/li&gt; &lt;li&gt;MySQL: シャーディングした Master × 5 / Slave × 9&lt;/li&gt; &lt;li&gt;Cassandra × 4&lt;/li&gt; &lt;li&gt;Membase × 15&lt;/li&gt; &lt;li&gt;Memcache × 8&lt;/li&gt; &lt;li&gt;Redis × 10&lt;/li&gt; &lt;li&gt;Task Router × 3 / Task Processors × 4&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.elasticsearch.org/" target="_blank" title="elasticsearch"&gt;Elastic Search&lt;/a&gt; Nodes&lt;/li&gt; &lt;li&gt;Mongo クラスタ&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;NoSQL 大好きですね。スライドには " &lt;span style="TEXT-DECORATION: underline"&gt;&lt;strong&gt;It will fail. Keep it simple.&lt;/strong&gt;&lt;/span&gt; " という教訓が書かれています。今後このまま利用するテクノロジーを増やしていくと、運用や変更コストがすごいことになります。2012/01 に以下のようなシンプルな構成に変更したそうです。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Amazon EC2 + S3 + ELB, &lt;span style="TEXT-DECORATION: underline"&gt;Akamai&lt;/span&gt;&lt;/li&gt; &lt;li&gt;Web Engines × 90 / API Engines × 50&lt;/li&gt; &lt;li&gt;MySQL: 66 (各 1 台のスレーブ)&lt;/li&gt; &lt;li&gt;Redis × 59&lt;/li&gt; &lt;li&gt;Memcache × 51&lt;/li&gt; &lt;li&gt;Redis Task Manager (&lt;a href="https://github.com/binarydud/pyres" target="_blank" title="Pyres - a Resque clone"&gt;pyres&lt;/a&gt;) × 1 / Task Processors ×25&lt;/li&gt; &lt;li&gt;&lt;a href="http://wiki.apache.org/solr/DistributedSearch" target="_blank" title="Distributed Searching"&gt;Sharded Solr&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Instagram 同様 nginx から ELB に変更、CDN を利用、Web サーバの更なる増加、MySQL のレプリケーション方法を変更、KVS を Redis に統一、タスク管理も Redis へ、memcache の増加、Elastic Search から Solr へ変更。だいぶシンプルになってます。&lt;a href="http://aws.amazon.com/jp/elasticloadbalancing/" target="_blank" title="Elastic Load Balancing"&gt;ELB&lt;/a&gt; は大人気ですね。また、Pinterest も Instagram 同様 KVS は redis に統一しています。シンプルです。&lt;/p&gt; &lt;p&gt;Pinterest がどのインスタンスを使っているかについては MySQL しか書いてありませんでした。Instagram は&lt;strong&gt;超&lt;/strong&gt;ハイエンドモデル 12 インスタンスで運用しているのに対し、Pinterest はハイエンドモデル 132 台です。双方のデータ量も QPS も分かりませんが、Pinterest が&lt;strong&gt;超&lt;/strong&gt;ハイエンドモデルに切り替えた場合の、運用コスト (メンテナンスコストを含む) を比較したら面白そうです。&lt;/p&gt; &lt;p&gt;参考: Extra Large インスタンス&lt;/p&gt; &lt;ul&gt; &lt;li&gt;15 GB メモリ&lt;/li&gt; &lt;li&gt;8 ECU（2 ECU × 4仮想コア）&lt;/li&gt; &lt;li&gt;1,690 GB インスタンスストレージ&lt;/li&gt; &lt;li&gt;64ビット プラットフォーム&lt;/li&gt; &lt;li&gt;I/O 性能: 高速15 GB memory&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Instagram が PostgreSQL で利用している Cluster Compute Quadruple Extra Large インスタンス&lt;/p&gt; &lt;ul&gt; &lt;li&gt;23 GB メモリ&lt;/li&gt; &lt;li&gt;33.5 EC2 Compute Unit（2 x Intel Xeon X5570、quad-core「Nehalem」アーキテクチャ）&lt;/li&gt; &lt;li&gt;1690 GB インスタンスストレージ&lt;/li&gt; &lt;li&gt;64ビット プラットフォーム&lt;/li&gt; &lt;li&gt;I/O 性能: 超高速（10 ギガビットイーサネット）&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; インフラの選択&lt;/p&gt; &lt;p&gt;スライドには各インフラを選択した理由が書かれています。Pinterest が技術を選択した理由に "&lt;span style="TEXT-DECORATION: underline"&gt;Well known and well liked&lt;/span&gt;" があげられています。この選択方法は私も大好きです。以下抜粋&lt;/p&gt; &lt;ul&gt; &lt;li&gt;AWS&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;信頼性が高く、報告やサポートが素敵&lt;/li&gt; &lt;li&gt;必要なものがそろってる&lt;/li&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;新しいインスタンスが数秒で起動する&lt;/span&gt;&lt;/li&gt; &lt;li&gt;選択肢が限られている w&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;MySQL&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;Well known and well liked&lt;/span&gt;&lt;/li&gt; &lt;li&gt;データの損失が皆無&lt;/li&gt; &lt;li&gt;&lt;a href="https://bugs.launchpad.net/percona-xtrabackup" target="_blank" title="Percona XtraBackup"&gt;XtraBackup&lt;/a&gt; (ノンブロックバックアップ), &lt;a href="http://code.google.com/p/innotop/" target="_blank" title="innotop"&gt;innotop&lt;/a&gt; (MySQL 用 top コマンド), &lt;a href="http://www.maatkit.org/" target="_blank" title="Maatkit"&gt;Maatkit&lt;/a&gt; (管理用便利コマンド類) 等の素敵なソフトがある&lt;/li&gt; &lt;li&gt;コミュニティが活発&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.percona.com/" target="_blank" title="Percona"&gt;Percona&lt;/a&gt; のサポートが素敵&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;memcache&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;Well known and well liked&lt;/span&gt;&lt;/li&gt; &lt;li&gt;成熟している&lt;/li&gt; &lt;li&gt;めったに落ちない&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;redis&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;Well known and well liked&lt;/span&gt;&lt;/li&gt; &lt;li&gt;使いやすいデータ構造&lt;/li&gt; &lt;li&gt;永続化とレプリカができる&lt;/li&gt; &lt;li&gt;一貫してパフォーマンスが高い&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; MySQL のスケール&lt;/p&gt; &lt;p&gt;特に MySQL は重点的に解説しています。MySQL クラスタとシャーディングを比較し、シャーディングを選んでいます。クラスタを選択しなかった理由は、&lt;/p&gt; &lt;ul&gt; &lt;li&gt;まだ出来たばかりの技術&lt;/li&gt; &lt;li&gt;コミュニティによるサポートが少ない&lt;/li&gt; &lt;li&gt;運用レベルのエンジニアが少ない&lt;/li&gt; &lt;li&gt;アップグレードが難しいし怖い&lt;/li&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;単一障害点になりえる&lt;/span&gt; (ここもうちょっと詳しく聞きたい)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;とのことです。&lt;/p&gt; &lt;p&gt;またシャーディングの選定理由は、&lt;/p&gt; &lt;ul&gt; &lt;li&gt;データベースを分割し、より多くのキャパを追加できる&lt;/li&gt; &lt;li&gt;高可用性&lt;/li&gt; &lt;li&gt;ロードバランシング&lt;/li&gt; &lt;li&gt;データ配置のアルゴリズムがシンプル&lt;/li&gt; &lt;li&gt;ID 生成がシンプル&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Pinterest では 512 個の DB を 8 台の物理サーバでシャーディングし、各ノードを Multi-Master レプリケーションで HA 構成にしているそうです。スライドには "Clustering is scary." という教訓で締められています。&lt;/p&gt; &lt;p&gt;うーむ。。。フェイルオーバ等 Multi-Master の制御をどうしているのか気になります。&lt;a href="http://mysql-mmm.org/" target="_blank" title="Multi-Master Replication Manager for MySQL"&gt;mmm&lt;/a&gt;? 私は Multi-Master を止めてクラスタを検討中なので、この辺りは再度勉強します。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;追記:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/methane/status/192168803994578944" target="_blank" title="@voluntas nginx使うと、バック側のWebサーバー一覧をnginxに教えないといけないんだけど、ELBを使うと負荷に応じてAWSが勝手にWebサーバー立ち上げてELBの分散対象に追加したり、逆に減らしたりしてくれるんです。"&gt;@methane&lt;/a&gt; 先生より ELB が素敵な理由: "@voluntas nginx使うと、バック側のWebサーバー一覧をnginxに教えないといけないんだけど、ELBを使うと負荷に応じてAWSが勝手にWebサーバー立ち上げてELBの分散対象に追加したり、逆に減らしたりしてくれるんです。"&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;参考:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://speakerdeck.com/u/yashh/p/scaling-pinterest" target="_blank" title="Scaling Pinterest"&gt;Scaling Pinterest&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.quora.com/Pinterest/What-technologies-were-used-to-make-Pinterest" target="_blank" title="http://www.quora.com/Pinterest/What-technologies-were-used-to-make-Pinterest"&gt;Pinterest: What technologies were used to make Pinterest?&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;-- &lt;br/&gt;ところで、AWS に興味がある方向けに "&lt;a href="http://jp.amazon-engineer.com/seminar.html" target="_blank" title="エンジニアオープンハウスイベント開催"&gt;エンジニアオープンハウスイベント&lt;/a&gt;" ってのがあるみたいです。2012年4月21日 （土）10:00〜12:30 　 に "運用・施設＆機械・インフラネットワーク系技術対象" ってのがあって、色々と AWS 中の人からインフラ系のお話が聞けるみたいです。どうしよう。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-3814178044556937331?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Mni2Wqdfz_WYqvxuZiJt57R7zME/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Mni2Wqdfz_WYqvxuZiJt57R7zME/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Mni2Wqdfz_WYqvxuZiJt57R7zME/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Mni2Wqdfz_WYqvxuZiJt57R7zME/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=OH3rRPepHlg:JA7ugICz4Ac:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=OH3rRPepHlg:JA7ugICz4Ac:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/OH3rRPepHlg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/3814178044556937331/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2012/04/pinterest.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/3814178044556937331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/3814178044556937331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/OH3rRPepHlg/pinterest.html" title="Pinterest のスケール" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2012/04/pinterest.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8ASH45eSp7ImA9WhVXFk4.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-3965234352303953639</id><published>2012-04-16T13:43:00.000+09:00</published><updated>2012-04-17T11:47:29.021+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-17T11:47:29.021+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="server" /><category scheme="http://www.blogger.com/atom/ns#" term="django" /><category scheme="http://www.blogger.com/atom/ns#" term="nginx" /><category scheme="http://www.blogger.com/atom/ns#" term="redis" /><category scheme="http://www.blogger.com/atom/ns#" term="instagram" /><category scheme="http://www.blogger.com/atom/ns#" term="ec2" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><category scheme="http://www.blogger.com/atom/ns#" term="postgresql" /><category scheme="http://www.blogger.com/atom/ns#" term="aws" /><title>Instagram のスケール正攻法</title><content type="html">&lt;p&gt;&lt;a href="http://instagr.am/" target="_blank" title="Instagram"&gt;Instagram&lt;/a&gt; がどこに買収されたとかは他のニュースサイトにお任せして、&lt;a href="https://djangoproject.com/" target="_blank" title="Django"&gt;Django&lt;/a&gt; アプリケーションを正攻法でスケールして "成功" してるのがとても興味深いです。現時点で &lt;a href="http://instagram-engineering.tumblr.com/" target="_blank" title="Instagram Engineering"&gt;Instagram Engineering&lt;/a&gt; で紹介されていることと &lt;a href="http://jp.techcrunch.com/archives/20120412how-to-scale-a-1-billion-startup-a-guide-from-instagram-co-founder-mike-krieger/" target="_blank" title="Instagramの共同ファウンダー、Mike Kriegerがゼロから10億ドルまで、開発の道のりを185枚のスライドで解説"&gt;TechCrunch にも掲載&lt;/a&gt;された&lt;a href="http://www.scribd.com/doc/89025069/Mike-Krieger-Instagram-at-the-Airbnb-tech-talk-on-Scaling-Instagram" target="_blank" title="Mike Krieger, Instagram at the Airbnb tech talk, on Scaling Instagram"&gt;スライド&lt;/a&gt;から個人的なメモとしてまとめてみました。&lt;/p&gt; &lt;p&gt;Instagram の哲学は&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;シンプル&lt;/span&gt;であること&lt;/li&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;オペレーション負荷を最小化&lt;/span&gt;すること&lt;/li&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;すべて装備&lt;/span&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;とのこと。&lt;/p&gt; &lt;p&gt;Instagram は以下の OSS, サービスで構築されているようです。&lt;/p&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; OS / ホスティング&lt;/p&gt; &lt;p&gt;Ubuntu Linux 11.04 を &lt;a href="http://aws.amazon.com/jp/ec2/" target="_blank" title="Amazon Elastic Compute Cloud"&gt;Amazon EC2&lt;/a&gt; にホスティング。以前のバージョンは高トラフィックになると固まる問題があったようです。運用は 3 人。EC2 にホスティングしている理由は、調査結果によるものではなく、"&lt;span style="TEXT-DECORATION: underline"&gt;まだ進化途中だから&lt;/span&gt;" だそうです。&lt;/p&gt; &lt;p&gt;ハードウェアの選定、導入、セットアップの手間も省けますし、パッケージ管理等の運用も軽そうですね。&lt;/p&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; ロードバランサ&lt;/p&gt; &lt;p&gt;&lt;a href="http://aws.amazon.com/jp/elasticloadbalancing/" target="_blank" title="Amazon Elastic Load Balancing"&gt;Amazon ELB&lt;/a&gt; を利用。もともとは DNS ラウンドロビン + nginx のロードバランサでバランシングしてたらしいですが、DNS の更新が遅いので止めたとのこと。nginx の負荷を軽減するために SSL も ELB までで、あとは HTTP。ELB はほんと素敵なサービスだと思います。DNS も &lt;a href="http://aws.amazon.com/jp/route53/" target="_blank" title="Amazon Route 53"&gt;Amazon Route 53&lt;/a&gt; を利用。GUI での管理が素敵とのことです。&lt;/p&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; アプリケーションサーバ&lt;/p&gt; &lt;p&gt;Django アプリケーションを EC2 の High-CPU Extra-Large インスタンスで実行。2012 年開始ぐらいでは約 25 インスタンスと書かれています。Android アプリを公開して 10 日で 1000 万ユーザ (20 時間で 100 万ユーザ) を獲得したようなので、今はもっと多いでしょうね。こういうサービスの拡大に柔軟に対応できるのも EC2 を含むクラウドの魅力だと思います。High-CPU にしている理由はおそらく PIL を多用するからでしょうか。WSGI サーバは &lt;a href="http://gunicorn.org/" target="_blank" title="Gunicorn"&gt;gunicorn&lt;/a&gt; ですよね。理由は Apache と mod_wsgi より CPU 負荷が軽かったからとのこと。デプロイは &lt;a href="http://www.fabfile.org/" target="_blank" title="Fabric"&gt;Fabric&lt;/a&gt; でやっているそうです。Fabric の使い方は &lt;a href="http://www.ianlewis.org/jp/fabric-pythonic" target="_blank" title="Fabric デプロイツールのPythonicな書き方"&gt;Ian 先生のブログ&lt;/a&gt;が参考になります。&lt;/p&gt; &lt;p&gt;あと、ボトルネックになってるプロセスを監視するために &lt;a href="https://bitbucket.org/evzijst/dogslow" target="_blank" title="evzijst / dogslow"&gt;dogslow&lt;/a&gt; という &lt;a href="http://bitbucket.org/" target="_blank" title="bitbucket"&gt;bitbucket&lt;/a&gt; 製の Django ミドルウェアを利用しているそうです。そういえば bitbucket も Django を使うメガサービスですね。&lt;/p&gt; &lt;p&gt;参考: High-CPU Extra-Large インスタンス&lt;/p&gt; &lt;ul&gt; &lt;li&gt;7 GB メモリ&lt;/li&gt; &lt;li&gt;20 ECU（2.5 ECU × 8仮想コア）&lt;/li&gt; &lt;li&gt;1690 GB インスタンスストレージ&lt;/li&gt; &lt;li&gt;64ビット プラットフォーム&lt;/li&gt; &lt;li&gt;I/O 性能: 高速&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; データストア&lt;/p&gt; &lt;p&gt;ほとんどのデータ (ユーザ、写真のメタデータ、タグ等) を PostgreSQL に保存。&lt;a href="https://docs.djangoproject.com/en/dev/faq/install/" target="_blank" title="What are Django’s prerequisites?"&gt;Django ドキュメント&lt;/a&gt;に "&lt;a title="PostgreSQL" href="http://www.postgresql.org/" class="reference external" target="_blank"&gt;PostgreSQL&lt;/a&gt; is recommended, because we're PostgreSQL fans" って書いてあるのを思い出しました。PostgreSQL は Cluster Compute Quadruple Extra Large インスタンスで実行。10 ギガですよ！同じく 2012 年開始ぐらいでは約 12 インスタンスと書かれています。またバックアップ用として異なるゾーンに 12 個のレプリカを置いているようです。&lt;a href="http://aws.amazon.com/jp/ebs/" target="_blank" title="Amazon Elastic Block Store"&gt;EBS&lt;/a&gt; のディスクシークが遅いので、すべてのワーキングセットをメモリに保存しているそうですPostgreSQL のレプリカは&lt;a href="http://www.postgresql.jp/document/9.1/html/warm-standby.html#STREAMING-REPLICATION" target="_blank" title="25.2.5. ストリーミングレプリケーション"&gt;ストリーミングレプリケーション&lt;/a&gt;を利用。レプリケーションの管理は &lt;a href="https://github.com/greg2ndQuadrant/repmgr" target="_blank" title="repmgr: Replication Manager for PostgreSQL clusters"&gt;repmgr&lt;/a&gt; を利用。バックアップは EBS のスナップショット機能を利用。コネクションプールに &lt;a href="http://wiki.postgresql.org/wiki/PgBouncer" target="_blank" title="PgBouncer"&gt;PgBouncer&lt;/a&gt; を利用 (これがパフォーマンス向上にかなり効いたらしい)。&lt;/p&gt; &lt;p&gt;最初は Django の&lt;a href="https://docs.djangoproject.com/en/dev/topics/db/multi-db/" target="_blank" title="Multiple databases"&gt;ルータ機能&lt;/a&gt;で垂直分割 (ハードウェア負荷の分散)。次に PostgreSQL のシャーディング (&lt;a href="http://lets.postgresql.jp/documents/technical/partitioning/1" target="_blank" title="パーティショニング : 用途と利点"&gt;参考&lt;/a&gt;) で水平分割 (データ領域の分散)。&lt;/p&gt; &lt;p&gt;参考: Cluster Compute Quadruple Extra Large インスタンス&lt;/p&gt; &lt;ul&gt; &lt;li&gt;23 GB メモリ&lt;/li&gt; &lt;li&gt;33.5 EC2 Compute Unit（2 x Intel Xeon X5570、quad-core「Nehalem」アーキテクチャ）&lt;/li&gt; &lt;li&gt;1690 GB インスタンスストレージ&lt;/li&gt; &lt;li&gt;64ビット プラットフォーム&lt;/li&gt; &lt;li&gt;I/O 性能: 超高速（10 ギガビットイーサネット）&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;次にメインフィード、アクティビティーフィード、セッションデータ (&lt;a href="https://gist.github.com/910392" target="_blank" title="A redis backend for Django Sessions, tested on Django 1.3+"&gt;django.contrib.sessions.backends&lt;/a&gt;) は &lt;a href="http://redis.io/" target="_blank" title="redis"&gt;redis&lt;/a&gt; に保存。redis は High-Memory Quadruple Extra Large インスタンスを数台。これもバックアップは EBS のスナップショット。redis のレプリカにより、簡単にオンラインフェールオーバする。redis を選択した理由は、"&lt;span style="TEXT-DECORATION: underline"&gt;インサートが高速&lt;/span&gt;、&lt;span style="TEXT-DECORATION: underline"&gt;サブセットの作成が高速&lt;/span&gt;" だったからとのこと。&lt;/p&gt; &lt;p&gt;参考: High-Memory Quadruple Extra Large インスタンス&lt;/p&gt; &lt;ul&gt; &lt;li&gt;68.4 GB メモリ&lt;/li&gt; &lt;li&gt;20 ECU（2.5 ECU × 8仮想コア）&lt;/li&gt; &lt;li&gt;1690 GB インスタンスストレージ&lt;/li&gt; &lt;li&gt;64ビット プラットフォーム&lt;/li&gt; &lt;li&gt;I/O 性能: 高速&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;ファイルシステムは XFS。&lt;/p&gt; &lt;p&gt;ファイルキャッシュを管理するために &lt;span class="l00006w00004" id="l00006w00004_1617"&gt;&lt;a href="https://github.com/hoytech/vmtouch" target="_blank" title="vmtouch - the Virtual Memory Toucher"&gt;&lt;span class="l00006w00004" id="l00006w00004_1617"&gt;v&lt;wbr/&gt;m&lt;wbr/&gt;t&lt;wbr/&gt;o&lt;wbr/&gt;u&lt;wbr/&gt;c&lt;wbr/&gt;h&lt;/span&gt;&lt;/a&gt; &lt;wbr/&gt;&lt;/span&gt;を利用。vmtouch でメモリにロードする。&lt;/p&gt; &lt;p&gt;私は KVS の選定の際、&lt;a href="http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis" target="_blank" title="Cassandra vs MongoDB vs CouchDB vs Redis vs Riak vs HBase vs Membase vs Neo4j comparison"&gt;ここ&lt;/a&gt;を参考にしています。&lt;/p&gt; &lt;p&gt;&amp;gt;&amp;gt;&amp;gt; タスクキューと PUSH 通知&lt;/p&gt; &lt;p&gt;写真を facebook や twitter 等への連携、新規写真や新規ユーザの通知等のタスクは &lt;a href="http://gearman.org/" target="_blank" title="gearman"&gt;gearman&lt;/a&gt; で処理。worker 数は 200 程度。&lt;/p&gt; &lt;p&gt;PUSH 通知は &lt;a href="https://github.com/samuraisam/pyapns" target="_blank" title="pyapns"&gt;pyapns&lt;/a&gt; (twisted powered) でやっている。&lt;/p&gt; &lt;p&gt;全体として、運用の手間を軽くし、フットワーク軽くサービスを提供できるように工夫されていますね。監視は &lt;a href="http://munin-monitoring.org/" target="_blank" title="Munin"&gt;munin&lt;/a&gt; を利用しているようです。プラグインを &lt;a href="http://samuelks.com/python-munin/" target="_blank" title="Python framework for building Munin plugins"&gt;python-munin&lt;/a&gt; で作成しているようです。監視まで pythonic ですね。python-munin には Instagram さんが利用しているインフラのための&lt;a href="https://github.com/samuel/python-munin/tree/master/plugins" target="_blank" title="python-munin / plugins"&gt;素敵なプラグイン&lt;/a&gt;が多く用意されています。もう 1 つ memcached も利用している技術の 1 つとして記載されていましたが、これについては残念ながら詳しくは書いてありませんでした。&lt;a href="http://aws.amazon.com/jp/elasticache/" target="_blank" title="Amazon ElastiCache"&gt;Amazon ElastiCache&lt;/a&gt; ですかね w&lt;/p&gt; &lt;p&gt;また、スライドには面白い tips も紹介されていました。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;favicon.ico は必ず作る&lt;/span&gt;こと: 404 error を防ぐ。最初のスケールはこれ。&lt;/li&gt; &lt;li&gt;他のサイトで以下に favicon を軽くするかも熱く解説していました&lt;/li&gt; &lt;li&gt;サービスもインフラもスピードも計量に&lt;/li&gt; &lt;li&gt;開発スタイル&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ol&gt; &lt;li&gt;大規模なユニットテストと機能テスト&lt;/li&gt; &lt;li&gt;DRY&lt;/li&gt; &lt;li&gt;シグナルによる祖結合&lt;/li&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;大部分を Python で完結し、必要に応じ C を利用&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&lt;span style="TEXT-DECORATION: underline"&gt;知識を共有するための頻繁なコードレビューとプルリクエスト&lt;/span&gt;&lt;/li&gt; &lt;li&gt;大規模な監視&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;参考:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.scribd.com/doc/89025069/Mike-Krieger-Instagram-at-the-Airbnb-tech-talk-on-Scaling-Instagram" target="_blank" title="Mike Krieger, Instagram at the Airbnb tech talk, on Scaling Instagram"&gt;Mike Krieger, Instagram at the Airbnb tech talk, on Scaling Instagram&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://instagram-engineering.tumblr.com/" target="_blank" title="Instagram Engineering"&gt;Instagram Engineering&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-3965234352303953639?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/O6lqQBCQa23pk-vDaRtBnw6OS3k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O6lqQBCQa23pk-vDaRtBnw6OS3k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/O6lqQBCQa23pk-vDaRtBnw6OS3k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O6lqQBCQa23pk-vDaRtBnw6OS3k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=J-TJBFuMnME:lX-CMyQx8NQ:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=J-TJBFuMnME:lX-CMyQx8NQ:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/J-TJBFuMnME" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/3965234352303953639/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2012/04/instagram.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/3965234352303953639?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/3965234352303953639?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/J-TJBFuMnME/instagram.html" title="Instagram のスケール正攻法" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2012/04/instagram.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIGRHc-fip7ImA9WhRWEEs.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-3984042362049726142</id><published>2011-12-27T01:21:00.000+09:00</published><updated>2011-12-28T17:55:25.956+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-28T17:55:25.956+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="redmine" /><category scheme="http://www.blogger.com/atom/ns#" term="reposearch" /><title>Redmine のリポジトリ全文検索プラグイン</title><content type="html">メリークリスマス！でしたね。今年のクリスマスは ruby を書いて過ごしました。えぇ。ついに ruby デビューです。
作ってたのは Redmine のリポジトリ全文検索プラグインです。会社のプロジェクト管理サイトを Trac から乗り換えるにあたり、これ！ってのが見つけられなかった情弱です。&lt;br /&gt;
Trac では、full-text サーチエンジンに &lt;a href="http://fallabs.com/hyperestraier/" target="_blank"&gt;Hyper Estraier&lt;/a&gt; を使う&amp;nbsp;&lt;a href="http://trac-hacks.org/wiki/RepoSearchPlugin" target="_blank"&gt;TracRepoSearch&lt;/a&gt;&amp;nbsp;という素晴らしいプラグインを使ってました。ということで、便乗して &lt;a href="http://surgo.github.com/redmine_reposearch/" target="_blank"&gt;redmine_reposearch&lt;/a&gt; というプラグインを作って見ました。バックエンドも同じく Hyper Estraier です。&lt;br /&gt;
&amp;nbsp;個人的に欲しかった機能は、&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;インストールステップが簡単&lt;/li&gt;
&lt;li&gt;プロジェクト、サブプロジェクト、全プロジェクト間で検索できる&lt;/li&gt;
&lt;li&gt;Redmine のアクセス権管理に対応する&lt;/li&gt;
&lt;li&gt;MIME タイプを限定して検索する (今後実装予定)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
です。ある程度は満足がいく出来に作ることが出来ました。インストール方法等は &lt;a href="https://github.com/Surgo/redmine_reposearch/wiki/Document-ja" target="_blank"&gt;wiki&lt;/a&gt; にまとめました。わかりにくかったらお気軽に Issue か Twitter でお申し付けください。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;# インストールステップは 2 ステップ&lt;/b&gt;&lt;br /&gt;
これは結構苦労しました。いろんな OSS 検索エンジンの仕様を調べ、一番インストールが簡単で、動作が軽快で、気の利いた ruby バインディングがあるやつを選びました。&lt;u&gt;ライブラリのインストールとプラグインのインストールのみで動作します。&lt;/u&gt;&lt;br /&gt;
Estraier の DB は &lt;code&gt;RAILS_VAR/reposearch&lt;/code&gt; 以下にプロジェクト毎に作成されます。Ubuntu の場合は、 &lt;code&gt;/var/lib/redmine/reposearch&lt;/code&gt; になります。クラスタ組みたい場合は、&lt;code&gt;RAILS_VAR&lt;/code&gt; はアップロードファイル保存ディレクトリでもあるので、ネットワークファイルシステムをマウントするなどすればいいと思います。&lt;br /&gt;
あと SCM との連携は &lt;a href="http://blog.redmine.jp/articles/redmine-0_9-url-to-fetch-changesets/" target="_blank"&gt;fetch_changesets&lt;/a&gt; と同じ仕組を流用しています。まだ &lt;code&gt;ruby script/runner "Repository.fetch_changesets" -e production&lt;/code&gt; のようなコマンドでは動きません。 /lib/crawl.rake なるものを作ればイケそうってとこまでは調べました。要望があれば。&lt;br /&gt;
インストールじゃなくて、インデックス作成もなるべく軽量になるように考えました。一応最終チェンジセットからの差分のみを再インデックス処理するようにしています。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;# プロジェクト、サブプロジェクト、全プロジェクト間で検索できる&lt;/b&gt;&lt;br /&gt;
これも Hyper Estraier を選んだ理由にもなります。DB をまたいで検索できますし、リポジトリ毎に DB を作成するので、インデックス破損の影響を最小限に抑えることができるかなと。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;# Redmine のアクセス管理に対応する&lt;/b&gt;&lt;br /&gt;
アクセス管理といわず、&lt;strike&gt;めんどくさいので&lt;/strike&gt;使えるものは既存のライブラリを使うようにしました。ページング処理、ワードハイライト、文字コード、SCM の差異吸収、アクセス可能なプロジェクトの選択、プロジェクト選択フィルタなどなど。&lt;a href="http://codesearch.redmine.jp/" target="_blank"&gt;Redmine code search&lt;/a&gt; さまさまです。他に使い回せそうなコードがあれば教えてください先生方。けっこう親和性高くできたと思います。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;# MIME タイプ限定検索など今後実装したい機能とか&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;テストを書きたい。書いてません。書き方わかりません。rails とか ruby とか勉強します&lt;/li&gt;
&lt;li&gt;MIME タイプ限定検索&lt;/li&gt;
&lt;li&gt;もっと軽量化したい。動作もコード量も&lt;/li&gt;
&lt;li&gt;マッチパートのシンタックスハイライト (挫折済み)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
言い訳を書いておくと、ruby も rails も redmine を初めて触ってるところです。Issue とかで色々教えていただけると喜びます。あと、他のプラットフォームでの動作確認とかも喜びます。&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-3984042362049726142?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0v39cyD1a0TdSaN0AAtDFxHs4_c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0v39cyD1a0TdSaN0AAtDFxHs4_c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0v39cyD1a0TdSaN0AAtDFxHs4_c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0v39cyD1a0TdSaN0AAtDFxHs4_c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=BfvYZz8C-SQ:saRJPTL7VX0:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=BfvYZz8C-SQ:saRJPTL7VX0:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/BfvYZz8C-SQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/3984042362049726142/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/12/redmine.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/3984042362049726142?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/3984042362049726142?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/BfvYZz8C-SQ/redmine.html" title="Redmine のリポジトリ全文検索プラグイン" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/12/redmine.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUABSHY6fCp7ImA9WhRQGE4.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-8999886668360653974</id><published>2011-12-14T13:06:00.001+09:00</published><updated>2011-12-14T13:42:39.814+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T13:42:39.814+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="unittest" /><category scheme="http://www.blogger.com/atom/ns#" term="py3k" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="test" /><title>Python の新ユニットテストフレームワーク (or unittest2)</title><content type="html">&lt;p&gt;これは &lt;a href="https://connpass.com/event/142/" target="_blank" title="2011 Pythonアドベントカレンダー(Python3)"&gt;Python3 Advent Calendar&lt;/a&gt; の記事です。夢はテストエンジニアです！ということでユニットテストについて書きます。&lt;/p&gt; &lt;p&gt;Python3 縛りとのことですが、この新ユニットテストフレームワークは Python &lt;strong&gt;3.2&lt;/strong&gt; 以降と &lt;strong&gt;2.7&lt;/strong&gt; 以降が対象です。これ以前のバージョンでこの新ユニットテストフレームワークを利用したい場合は、それぞれ &lt;a href="http://pypi.python.org/pypi/unittest2py3k" target="_blank" title="unittest2py3k"&gt;unittest2py3k&lt;/a&gt; (3 系)、 &lt;a href="http://pypi.python.org/pypi/unittest2" target="_blank" title="unittest2"&gt;unittest2&lt;/a&gt; (2 系) というバックポートが用意されています。新ユニットテストは &lt;a href="http://pypi.python.org/pypi/mock" target="_blank" title="mock"&gt;mock&lt;/a&gt; や IronPython 等の開発者としても知られている &lt;a href="http://www.voidspace.org.uk/" target="_blank" title="Voidspace - The website, technical blog and projects of Michael Foord"&gt;Michael Foord&lt;/a&gt; 氏を中心に開発されました。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; Python とユニットテストの歴史&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Python のユニットテストは、1999 年 &lt;a href="http://ja.wikipedia.org/wiki/XUnit" target="_blank" title="xUnit - Wikipedia"&gt;xUnit&lt;/a&gt; ファミリーの &lt;a href="http://pyunit.sourceforge.net/pyunit.html" target="_blank" title="PyUnit"&gt;PyUnit&lt;/a&gt; として開発され、2001 年に公開された Python 2.1 から unittest として標準ライブラリとなりました。それ以降、アップグレードといえば assert* メソッドの追加や削除といった感じ。PyCon 2010 での Michael Foord 氏の&lt;a href="http://python.mirocommunity.org/video/1548/pycon-2010-new-and-improved-co" target="_blank" title="PyCon 2010: New *and* Improved: Coming changes to unittest, the standard library test framework (#52)"&gt;プレゼンテーション&lt;/a&gt;によると "&lt;span style="TEXT-DECORATION: underline"&gt;Python には革新的なテストインフラが数多くありますが、unittest は標準ライブラリという理由により最も利用されているテストフレームワークです。しかし、他のテストフレームワークが革新的な進歩を遂げている中、unittest は遅れを取っています&lt;/span&gt;"。&lt;/p&gt; &lt;p&gt;しかしついに、ユニットテストは Python 3.2, 2.7 で革新されることになりました。それも Python らしく "後方互換" がかなり意識されています。これも Michael Forrd 氏の言葉を借りると "&lt;span style="TEXT-DECORATION: underline"&gt;これは革命ではなく、&lt;strong&gt;進化&lt;/strong&gt;です&lt;/span&gt;"。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; どこが "進化" したのか&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;新ユニットテストフレームワークには以下の機能の追加や更新が行われています。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;便利な &lt;code class="prettyprint"&gt;assert*&lt;/code&gt; メソッドの追加&lt;/li&gt; &lt;li&gt;名称の統一、重複の排除&lt;/li&gt; &lt;li&gt;コマンドラインからの制御をより便利に / 或いはディスカバリ&lt;/li&gt; &lt;li&gt;テストのスキップ&lt;/li&gt; &lt;li&gt;モジュールレベル、クラスレベルのテストフィクスチャ&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;などなどです。各進化の詳細について解説していきたいと思います。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; 便利な &lt;code class="prettyprint"&gt;assert*&lt;/code&gt; メソッドの追加&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;追加されたメソッドには以下が含まれています。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;3.1 以降に追加されたメソッドも含んでいます&lt;/li&gt; &lt;li&gt;3.2 / 3.3 で非推奨 / 廃止されたメソッドは含んでいません&lt;/li&gt; &lt;li&gt;3.2 / 3.3 で名称変更されたものは新名称で記載しています&lt;/li&gt; &lt;li&gt;利用できるメソッドはバージョンによって違うので、確認する必要があります&lt;/li&gt; &lt;/ul&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;メソッド&lt;/th&gt; &lt;th&gt;検証内容&lt;/th&gt; &lt;th&gt;Ver.&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;assertIsNone / assertIsNotNone(x, msg=None)&lt;/td&gt; &lt;td&gt;x is [not] None&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertIs / assertIsNot(a, b)&lt;/td&gt; &lt;td&gt;a is [not] b&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertIn / assertNotIn(a, b)&lt;/td&gt; &lt;td&gt;a [not] in b&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertIsInstance / assertNotIsInstance(a, b)&lt;/td&gt; &lt;td&gt;[not] isinstance(a, b)&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertGreater / assertGreaterEqual(a, b) &lt;br/&gt;assertLess / assertLessEqual(a, b)&lt;/td&gt; &lt;td&gt;a &amp;gt;[=] b &lt;br/&gt;a &amp;lt;[=] b&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertAlmostEqual / assertNotAlmostEqual(a, b)&lt;/td&gt; &lt;td&gt;round(a-b, 7) [!|=]= 0 &lt;br/&gt;※ 仕様変更 (delta を追加)&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertRegex / assertNotRegex(s, re)&lt;/td&gt; &lt;td&gt;[not] re.search(s)&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1 (not は &amp;gt;= 3.2)&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertCountEqual(a, b)&lt;/td&gt; &lt;td&gt;配列の個数と値&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertMultiLineEqual(a, b)&lt;/td&gt; &lt;td&gt;a = b: 文字列&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertSequenceEqual(a, b)&lt;/td&gt; &lt;td&gt;a = b: 配列+タイプ&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertListEqual(a, b)&lt;/td&gt; &lt;td&gt;a = b: list&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertTupleEqual(a, b)&lt;/td&gt; &lt;td&gt;a = b: tuple&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertSetEqual(a, b)&lt;/td&gt; &lt;td&gt;a = b: set&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertDictEqual(a, b)&lt;/td&gt; &lt;td&gt;a = b: dict&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertRaises(exc, fun, *args, **kwds)&lt;/td&gt; &lt;td&gt;fun(*args, **kwds) raises exc&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1 &lt;br/&gt;※ 3.2, 3.3 で仕様変更&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertRaisesRegex(exc, re, fun, *args, **kwds)&lt;/td&gt; &lt;td&gt;fun(*args, **kwds) raises exc \ &lt;br/&gt;and re.match(exc.message)&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.1 &lt;br/&gt;※ 3.2, 3.3 で仕様変更&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertWarns(warn, fun, *args, **kwds)&lt;/td&gt; &lt;td&gt;fun(*args, **kwds) raises warn&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;assertWarnsRegex(warn, re, fun, *args, **kwds)&lt;/td&gt; &lt;td&gt;fun(*args, **kwds) raises warn \ &lt;br/&gt;and re.match(exc.message)&lt;/td&gt; &lt;td&gt;&amp;gt;= 3.2&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;これは Google さんの協力も得て追加されたようです。このメリットをいくつか挙げたいと思います。&lt;/p&gt; &lt;p&gt;まず、&lt;span style="TEXT-DECORATION: underline"&gt;a=b 等の状態検証用のメソッドが増えた&lt;/span&gt;こと。テスト開発者の皆様も待ち望んでいたのではないでしょうか？なんでこれが幸せなのか。既存の &lt;code class="prettyprint"&gt;assert*&lt;/code&gt; を駆使して作ってたメソッドが 1 行で検証できるようになり、バグを発見しやすくなります。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
class TestTest(unittest.TestCase):
    def setUp(self):
        self.list_first = [1, 2, 3, 4, ]
        self.list_second = [1, 2, 4, 4, 5, ]

    def test_old(self):
        self.assertEqual(len(self.list_first), len(self.list_second))
        self.assertEqual(self.list_first, self.list_second)

    def test_new(self):
        self.assertCountEqual(self.list_first, self.list_second)

if __name__ == '__main__':
    unittest.main()
&lt;/pre&gt;
 &lt;p&gt;例がむちゃくちゃでごめんなさい。。。&lt;/p&gt; 
&lt;pre&gt;
======================================================================
FAIL: test_new (__main__.TestTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_test.py", line 14, in test_new
    self.assertCountEqual(self.list_first, self.list_second)
AssertionError: Element counts were not equal:
First has 1, Second has 0:  3
First has 1, Second has 2:  4
First has 0, Second has 1:  5

======================================================================
FAIL: test_old (__main__.TestTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_test.py", line 10, in test_old
    self.assertEqual(len(self.list_first), len(self.list_second))
AssertionError: 4 != 5

----------------------------------------------------------------------
Ran 2 tests in 0.000s
&lt;/pre&gt;
 &lt;p&gt;テスト結果を見ても、&lt;code class="prettyprint"&gt;4 != 5&lt;/code&gt; じゃなんのことかさっぱりですよね。以前は "テストメソッド数 ＝ 機能数" というのが一般的でしたが、モダンなテストは "テストメソッド ≒ 検証" です。ひとつのテストメソッド (&lt;code class="prettyprint"&gt;test_*&lt;/code&gt;) 内に複数の検証 (&lt;code class="prettyprint"&gt;assert*&lt;/code&gt;) を書いた場合、複数のテストに失敗しても最初の失敗しか出力されません。「分割すると時間がかかるし、まとめると失敗したときに追いかけるの大変だし。。。しゃーない独自の &lt;code class="prettyprint"&gt;assert*&lt;/code&gt; 定義するか」ってな悩みから解放されます。&lt;/p&gt; &lt;p&gt;また、失敗時の結果出力もバグが分かりやすいように大幅に改善されています。&lt;/p&gt; 
&lt;pre&gt;
### Python 2.6
AssertionError: [1, 2, 3, 4] != [1, 2, 4, 4, 5]
&lt;/pre&gt;
 
&lt;pre&gt;
### Python 3.2
AssertionError: Lists differ: [1, 2, 3, 4] != [1, 2, 4, 4, 5]

First differing element 2:
3
4

Second list contains 1 additional elements.
First extra element 4:
5

- [1, 2, 3, 4]
?        ^

+ [1, 2, 4, 4, 5]
?        ^   +++
&lt;/pre&gt;
 &lt;p&gt;適材適所の &lt;code class="prettyprint"&gt;assert*&lt;/code&gt; を使うことで、バグを見つけやすくなります。&lt;/p&gt; &lt;p&gt;次に、&lt;span style="TEXT-DECORATION: underline"&gt;assertRaises も大きな変更の 1 つ&lt;/span&gt;です。以前は &lt;code class="prettyprint"&gt;try-catch&lt;/code&gt; で書いていた検証が 1 行で書けるようになりました。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
class TestTest(unittest.TestCase):
    def test_old(self):
        try:
            int("spam")
            self.fail("Expected a ValueError")
        except (Exception, ) as e:
            self.assertTrue(isinstance(e, ValueError))

    def test_new(self):
        self.assertRaises(ValueError, int, "spam")

if __name__ == '__main__':
    unittest.main()
&lt;/pre&gt;
 &lt;p&gt;このテストはもう 1 つ問題があります。例外が発生しない場合は、"&lt;code class="prettyprint"&gt;self.fail&lt;/code&gt;" が通らないことですね。テストのカバレッジも重要ですが、テスト自体のカバレッジも大切です。&lt;code class="prettyprint"&gt;try&lt;/code&gt; 節が長くなったり、ネストしたりするとテストが複雑になってしまいます。通らない可能性があるコードなんて書かないようにしましょう (書いてて耳が痛い)。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; 名称の統一、重複の排除&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;追加された便利機能もあれば、非推奨になったものもあります。名称の統一と重複の解除により、以下のメソッドが非推奨になりました。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;assert_&lt;/code&gt;: &lt;code class="prettyprint"&gt;assertTrue&lt;/code&gt; を利用する&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;fail*&lt;/code&gt;: &lt;code class="prettyprint"&gt;assert*&lt;/code&gt; を利用する&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;assertEquals: &lt;code class="prettyprint"&gt;assertEqual&lt;/code&gt; に統一&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;バージョンによって推奨・非推奨は異なっています。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; コマンドラインからの制御をより便利に / 或いはディスカバリ&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;code class="prettyprint"&gt;unittest&lt;/code&gt; モジュールはコマンドラインから使えます (&lt;a href="http://answer.pythonpath.jp/questions/506/python-m" target="_blank" title="pythonの-m指定で便利なモジュール類"&gt;参考&lt;/a&gt;)。これに、py.test や nose とまではいきませんが、&lt;span style="TEXT-DECORATION: underline"&gt;ディスカバリ機能&lt;/span&gt;が追加されました！&lt;/p&gt; 
&lt;pre&gt;
# テストモジュールやテストクラスを指定して実行
python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
# ファイル名を指定して実行
python -m unittest tests/test_something.py
# 結果の詳細出力 (verbosity=3)
python -m unittest -v test_module
# ディスカバリ実行 &amp;lt;- New!!!
python -m unittest
python -m unittest discover
&lt;/pre&gt;
 &lt;p&gt;ディスカバーと便利なオプションたち。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-v&lt;/code&gt;, &lt;code class="prettyprint"&gt;--verbose&lt;/code&gt;: 結果を詳細に出力する&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-f&lt;/code&gt;, &lt;code class="prettyprint"&gt;--failfast&lt;/code&gt;: &lt;span style="TEXT-DECORATION: underline"&gt;最初に失敗した所でテストを終了&lt;/span&gt;する (&amp;gt;= 3.2)&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-c&lt;/code&gt;, &lt;code class="prettyprint"&gt;--catch&lt;/code&gt;: &lt;span style="TEXT-DECORATION: underline"&gt;テストを中断し、それまでに実行したテスト結果を出力&lt;/span&gt;する (&amp;gt;= 3.2)&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-b&lt;/code&gt;, &lt;code class="prettyprint"&gt;--buffer&lt;/code&gt;: &lt;span style="TEXT-DECORATION: underline"&gt;出力先を指定&lt;/span&gt;する (&amp;gt;= 3.2)&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-s&lt;/code&gt;: ディスカバリを開始するディレクトリ (&amp;gt;= 3.2)&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-p&lt;/code&gt;: ディスカバリ時にテストファイルにマッチさせるパターン (&amp;gt;= 3.2)&lt;/li&gt; &lt;li&gt;&lt;code class="prettyprint"&gt;-t&lt;/code&gt;: ディスカバリさせたいプロジェクトのトップレベルディレクトリ (&amp;gt;= 3.2)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;code class="prettyprint"&gt;-v&lt;/code&gt;, &lt;code class="prettyprint"&gt;-f&lt;/code&gt;, &lt;code class="prettyprint"&gt;-c&lt;/code&gt;, &lt;code class="prettyprint"&gt;-b&lt;/code&gt; についてはディスカバリ時以外でも使えます。&lt;/p&gt; 
&lt;pre&gt;
python -m unittest discover -s project_directory -p '*_test.py'
python -m unittest discover project_directory '*_test.py'
&lt;/pre&gt;
 &lt;p&gt;ディスカバリのために、&lt;code class="prettyprint"&gt;load_tests&lt;/code&gt; プロトコルが追加されています。テストモジュールに &lt;code class="prettyprint"&gt;TestSuite&lt;/code&gt; を返す &lt;code class="prettyprint"&gt;load_tests&lt;/code&gt; を定義することにより、テストを制御することができます。例えば以下の例ではディスカバリする際のテストクラスを限定しています。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
test_cases = (TestCase1, TestCase2, TestCase3)

def load_tests(loader, tests, pattern):
    suite = TestSuite()
    for test_class in test_cases:
        tests = loader.loadTestsFromTestCase(test_class)
        suite.addTests(tests)
    return suite
&lt;/pre&gt;
 &lt;p&gt;限定しなければ、&lt;code class="prettyprint"&gt;TestCase&lt;/code&gt; を継承するすべてのクラスがテスト対象となります。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; テストのスキップ&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;テストクラスとテストメソッドをスキップ出来るようになりました。スキップする条件も指定できます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
class TestTest(unittest.TestCase):
    @unittest.skip("無条件スキップ")
    def test_nothing(self):
        self.fail("shouldn't happen")

    @unittest.skipIf(mylib.__version__ &amp;lt; (1, 3),
                     "not supported in this library version")
    def test_format(self):
        # 指定したバージョンのライブラリでのみテスト
        pass

    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_windows_support(self):
        # Windows でのみテスト
        pass
&lt;/pre&gt;
 &lt;p&gt;verbosity を指定して実行すると以下のように出力されます。&lt;/p&gt; 
&lt;pre&gt;
$ python -m unittest -v test.py
test_nothing (test_test.TestTest) ... skipped '無条件スキップ'
test_format (__main__.TestTest) ... skipped 'not supported in this library version'
test_windows_support (__main__.TestTest) ... skipped 'requires Windows'
&lt;/pre&gt;
 &lt;p&gt;テストクラスごとスキップする場合は、以下のように書きます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
@skip("showing class skipping")
class TestTest(unittest.TestCase):
    def test_not_run(self):
        pass
&lt;/pre&gt;
 &lt;p&gt;&lt;del&gt;どういう場合に有効なのかわかりませんが&lt;/del&gt; 失敗した場合でも失敗と数えないようにするデコレータも追加されています。テスト作成時には失敗するけど、修正してテストが成功すると通知してくれます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
    @unittest.expectedFailure
    def test_fail(self):
        self.assertEqual(1, 0, "broken")
&lt;/pre&gt;
 
&lt;pre&gt;
# テストに成功してしまった場合の出力
test_fail (test_test.TestTest) ... unexpected success
&lt;/pre&gt;
 &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; モジュールレベル、クラスレベルのテストフィクスチャ&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;これもテストコードも綺麗に書きたい方にとって待ち望んでいた機能だと思います。&lt;code class="prettyprint"&gt;setUp&lt;/code&gt; / &lt;code class="prettyprint"&gt;tearDown&lt;/code&gt; が無駄に長かったり、テストメソッド間で共有したいクラスレベル変数をメソッドレベルに定義したり。。。これは神アップデートです。&lt;span style="TEXT-DECORATION: underline"&gt;テストがシンプル&lt;/span&gt;に、&lt;span style="TEXT-DECORATION: underline"&gt;メンバの&lt;/span&gt; &lt;span style="TEXT-DECORATION: underline"&gt;スコープも最小限&lt;/span&gt;に抑えることができます！！！そういえばモダンな xUnit では setUp/tearDown をなくしちゃった言語もありますね。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# Old... orz
connection = createExpensiveConnectionObject()

class TestTest(unittest.TestCase):
    def test_spam(self):
        connection
&lt;/pre&gt;
 &lt;p&gt;コネクションが違う場合は別モジュール orz...&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# New !!!
class TestTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._connection = createExpensiveConnectionObject()

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()

    def test_spam(self):
        cls._connection
&lt;/pre&gt;
 &lt;p&gt;スコープが素敵ですよね！スコープ範囲のためにモジュールやクラスを分割する必要がなくなります！上述のように "テストメソッド ≒ 検証" 形式で書いても、無駄に &lt;code&gt;setUp&lt;/code&gt; を実行しないで済みます。&lt;/p&gt; &lt;p&gt;モジュールレベルは以下のように書けます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()
&lt;/pre&gt;
 &lt;p&gt;&lt;code class="prettyprint"&gt;setUp&lt;/code&gt; / &lt;code class="prettyprint"&gt;tearDown&lt;/code&gt; の代替手段として &lt;code class="prettyprint"&gt;addCleanup&lt;/code&gt; というメソッドが作られています。 &lt;code class="prettyprint"&gt;addCleanup&lt;/code&gt; を使うことで、可読性が高いリソースのセットアップ処理 / 終了処理を書くことができるようになります。 これはテストの終了時 (LIFO) の動作が保障されています。&lt;code class="prettyprint"&gt;tearDown&lt;/code&gt; は &lt;code class="prettyprint"&gt;setUp&lt;/code&gt; 失敗時には動作しません。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
def test_method(self):
    temp_dir = tempfile.mkdtemp()
    self.addCleanup(shutil.rmtree, temp_dir)
    ...
&lt;/pre&gt;
 &lt;p&gt;明示的に呼び出したい場合は、以下のように書けます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
def test_method(self):
    temp_dir = tempfile.mkdtemp()
    self.addCleanup(shutil.rmtree, temp_dir)
    ...
    self.doCleanups()
    ...
    self.doCleanups()
&lt;/pre&gt;
 &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; まとめ&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;新ユニットテストフレームワーク素晴らしいですよね！バックポートも用意されていますので、是非移行しましょう！バックポートにはディスカバリ等に制限がありますが、&lt;code class="prettyprint"&gt;assert*&lt;/code&gt; メソッドやテストフィクスチャの恩恵を受けることができます。バックポートとの後方互換を持たせるため、以下のように &lt;code class="prettyprint"&gt;import&lt;/code&gt; することが推奨されています。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
try:
    import unittest2 as unittest
except (ImportError):
    import unittest
&lt;/pre&gt;
 &lt;p&gt;新ユニットテストフレームワークには他にも多くの便利機能が用意されています。詳細については&lt;a href="http://docs.python.org/dev/library/unittest.html" target="_blank" title="unittest — Unit testing framework"&gt;公式ドキュメント&lt;/a&gt;を参照してください。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt;&amp;gt; Python 3 に対応しているテストソリューション&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;テストフレームワーク: &lt;a href="http://pypi.python.org/pypi/nose/" target="_blank" title="nose"&gt;nose&lt;/a&gt;, &lt;a href="http://pypi.python.org/pypi/pytest/" target="_blank" title="py.test"&gt;py.test&lt;/a&gt;&lt;/li&gt; &lt;li&gt;テスト用モック: &lt;a href="http://pypi.python.org/pypi/mock/" target="_blank" title="mock"&gt;mock&lt;/a&gt;&lt;/li&gt; &lt;li&gt;TDD ならぬ BDD (ビヘイビアドリブン開発) フレームワーク: &lt;a href="http://pypi.python.org/pypi/python-specfor/" target="_blank" title="python-specfor"&gt;python-specfor&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;BDDフレームワークの &lt;a href="http://pypi.python.org/pypi/Pyccuracy/" target="_blank" title="PyCcuracy"&gt;PyCcuracy&lt;/a&gt; 等も今後の対応に期待したいですね。&lt;/p&gt; &lt;p&gt;ということで次は最近お子様が誕生された "@mopemope" 先生にバトンタッチです。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-8999886668360653974?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/b_5pdY5cy4uzXnrT-SIM1V79fRI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/b_5pdY5cy4uzXnrT-SIM1V79fRI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/b_5pdY5cy4uzXnrT-SIM1V79fRI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/b_5pdY5cy4uzXnrT-SIM1V79fRI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=8jnJnlouYPY:VrYTYuOzCwI:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=8jnJnlouYPY:VrYTYuOzCwI:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/8jnJnlouYPY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/8999886668360653974/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/12/python-or-unittest2.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/8999886668360653974?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/8999886668360653974?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/8jnJnlouYPY/python-or-unittest2.html" title="Python の新ユニットテストフレームワーク (or unittest2)" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/12/python-or-unittest2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEFRn47cCp7ImA9WhRQGE4.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-2814002392538206536</id><published>2011-12-14T11:10:00.000+09:00</published><updated>2011-12-14T13:40:17.008+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T13:40:17.008+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="pypy" /><title>PyPy における Python のパフォーマンスチューニング</title><content type="html">&lt;p&gt;これは &lt;a href="http://atnd.org/events/22078" target="_blank" title="2011 PyPy アドベントカレンダー"&gt;PyPy Advent Calendar&lt;/a&gt; の記事です。PyPyのコアディベロッパーである "&lt;a href="https://twitter.com/#!/fijall" target="_blank" title="@fijall"&gt;Maciej Fijalkowski&lt;/a&gt;" 氏のブログ "&lt;a href="http://lostinjit.blogspot.com/2011/11/analysing-pythons-performance-under.html" target="_blank" title="Analysing python's performance under PyPy"&gt;Analysing python's performance under PyPy&lt;/a&gt;" の抄訳+αです。&lt;/p&gt; &lt;p&gt;Python の一般的なパフォーマン解析のモデルは、"&lt;a href="http://www.python.jp/doc/nightly/library/profile.html" target="_blank" title="Python プロファイラ"&gt;プロファイラ&lt;/a&gt;を実行して、ボトルネックを探し出し、それを最適化するか C で書き直す" ことです。しかし PyPy ではこのアプローチだけでは不十分です。なぜなら、&lt;/p&gt; &lt;ul&gt; &lt;li&gt;多くの大規模アプリケーションで、プロファイラはフラットです: PyPy のトランスレーションツールチェーン、Twisted、モダンな Web サーバ等が良い例です&lt;/li&gt; &lt;li&gt;ボトルネックを発見したとしても、それが特定の関数内でのみ遅いのか、複数の関数が関係しているのか明確になるわけではありません。どうすれば遅くて、どうすれば速くなるかは CPython においても明確な答えはありません。JIT が適用されるとさらに複雑です。 &lt;em&gt;JIT が特定のコードをどのようにコンパイルしたかを確認することが重要&lt;/em&gt;になります。&lt;/li&gt; &lt;li&gt;パフォーマンスにおいては、特に GC 関連の問題は多くの関数に影響がありますが、プロファイルでは確認できません。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;PyPy には、問題を解決するためのいくつかのツールが提供されています。プログラムのパフォーマン解析に関するいくつかの方法を示します。これはガイドラインであり、&lt;em&gt;銀の弾丸&lt;/em&gt;ではありません。アプリケーションが複雑な場合は、多くの&lt;em&gt;鉛の弾丸&lt;/em&gt;が必要でしょう。&lt;/p&gt; &lt;p&gt;          &lt;strong&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; テストを作成する&lt;/strong&gt;        &lt;/p&gt; &lt;p&gt;これは品質に関するものではありません。多くの自動化されたテストを受けることで、その機能を失うことなく、よりパフォーマンスの高いコードにリファクタできるようにします。&lt;/p&gt; &lt;p&gt;          &lt;strong&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ベンチマークを書く&lt;/strong&gt;        &lt;/p&gt; &lt;p&gt;これが重要な出発点となります。ひとつのスクリプトで、できれば引数を指定して、変更の影響を測定できるようにする必要があります。&lt;/p&gt; &lt;p&gt;1 回だけしか実行されないスクリプトでない場合は、同じテストを繰り返し実行することで JIT のウォームアップ時間がパフォーマンスにどのような影響があるかを測定することができます。それは連続して実行されるとどのように変化するかを視覚化する助けにもなります。&lt;/p&gt; &lt;p&gt;"Maciej Fijalkowski" さんのベンチマークは、ステップごとに 0.2 秒から 5 秒実行しているそうです。これにより、誤差を最小限にすることができます。JIT のウォーミングアップ時間は、コードベースによって違ってきます。それは一瞬かもしれませんし、1 分かもしれません。&lt;/p&gt; &lt;p&gt;          &lt;strong&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; cProfile の結果を考慮する&lt;/strong&gt;        &lt;/p&gt; &lt;p&gt;Python のプロファイラ (cProfile) をカスタマイズした &lt;a href="https://bitbucket.org/pypy/pypy/src/default/pypy/tool/lsprofcalltree.py" target="_blank" title="lsprofcalltree.py"&gt;lsprofcalltree.py&lt;/a&gt; を利用し、&lt;a href="http://kcachegrind.sourceforge.net/html/Home.html" target="_blank" title="KCachegrind"&gt;kcachegrid&lt;/a&gt; へ取り込み可能なフォーマットで出力します。これは役に立つ情報を提供するかもしれませんし、しないかもしれません。プロファイルから突出している関数がある場合に、その効率やアルゴリズムを確認します。&lt;/p&gt; &lt;p&gt;          &lt;strong&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; GC や JIT 等の比率を確認する&lt;/strong&gt;        &lt;/p&gt; &lt;p&gt;PyPy のコードベースには、この確認に便利なツールが提供されています。プログラムを pypy virtualenv で実行している場合は:&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
$ PYPYLOG=log ./test.py
&lt;/pre&gt;
 &lt;p&gt;を実行します。また、pypy のリポジトリのチェックアウトから:&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
$ pypy/tool/logparser.py print-summary log -
&lt;/pre&gt;
 &lt;p&gt;を実行します。また、グラフで確認したい場合は:&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
$ pypy/tool/logparser.py draw-time log out.png
&lt;/pre&gt;
 &lt;p&gt;を実行します。これは、だいたい何にどれぐらいの時間が費やされているかを確認することができます。GC、JIT トレース (ウォームアップ時間)、その他 JIT 化されたコードの実行時間が含まれています。&lt;/p&gt; &lt;p&gt;logparser の出力例については、&lt;a href="http://d.hatena.ne.jp/rokujyouhitoma/20111207/1323268320" target="_blank" title="[PyPy]RPythonToolChainでOok!を実装した時のノウハウ紹介。PyPy Advent Calendar 2011 7日目"&gt;PyPy Advent calendar: 7 日目の id:rokujyouhitoma (総帥) 先生のブログ&lt;/a&gt;が参考になります。&lt;/p&gt; &lt;p&gt;          &lt;strong&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/strong&gt; &lt;a href="https://bitbucket.org/pypy/jitviewer" target="_blank" title="jitviewer"&gt;            &lt;strong&gt;jitviewer&lt;/strong&gt;          &lt;/a&gt; &lt;strong&gt;を利用する&lt;/strong&gt;        &lt;/p&gt; &lt;p&gt;jitviewer により、コードに何が起きたかを大まかに確認することができます。&lt;/p&gt; &lt;p&gt;          &lt;em&gt;インストール方法 (Ubuntu)&lt;/em&gt;        &lt;/p&gt; &lt;p&gt;以下がインストールされていることが前提です。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;virtualenvwrapper or virtualenv&lt;/li&gt; &lt;li&gt;pypy-1.7 &lt;p&gt;※ PyPy は /opt/ 配下にインストールし、 /usr/bin にシンボリックリンク作ってます。&lt;/p&gt; 
&lt;pre&gt;
cd /opt/
wget https://bitbucket.org/pypy/pypy/downloads/pypy-1.7-linux.tar.bz2
tar -jxf pypy-1.7-linux.tar.bz2
sudo ln -s /opt/pypy-1.7/bin/pypy /usr/bin/
&lt;/pre&gt;
          &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;jitviewer 用の virtualenv を作成し、インストールします。&lt;/p&gt; 
&lt;pre&gt;
mkvirtualenv pypy-viewer -p /usr/bin/pypy
pip install JitViewer
# 開発版を使われたい方: pip install -e hg+https://bitbucket.org/pypy/jitviewer/#egg=jitviewer
&lt;/pre&gt;
 &lt;p&gt;最後に PYTHONPATH に &lt;code&gt;/opt/pypy-1.7/lib_pypy&lt;/code&gt;, &lt;code&gt;lib-python&lt;/code&gt;, &lt;code&gt;py&lt;/code&gt; を追加します。&lt;/p&gt; &lt;div style="CLEAR: both; TEXT-ALIGN: center" class="separator"&gt;          &lt;a style="MARGIN-LEFT: 1em; MARGIN-RIGHT: 1em" href="http://1.bp.blogspot.com/-qxQ8KlIfy1k/TugDKcc1YhI/AAAAAAAAHuM/-TJaWvhgxLo/s1600/jitviewer.png"&gt;            &lt;img src="http://1.bp.blogspot.com/-qxQ8KlIfy1k/TugDKcc1YhI/AAAAAAAAHuM/-TJaWvhgxLo/s320/jitviewer.png" height="317" border="0" width="320"/&gt;          &lt;/a&gt;        &lt;/div&gt; &lt;p&gt;こんな感じで JIT ログ + アセンブラを確認することができます (&lt;a href="https://sites.google.com/site/pypyja/skype-matome/jitviewer-assembler" target="_blank" title="jitviewer からの CPU アーキテクチャやらアセンブラやらの話"&gt;これを見て盛り上がる pypyja のチャット&lt;/a&gt;)。&lt;/p&gt; &lt;p&gt;          &lt;strong&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; JIT にやさしいコード&lt;/strong&gt;        &lt;/p&gt; &lt;p&gt;本家にある &lt;a href="https://bitbucket.org/pypy/pypy/wiki/JitFriendliness" target="_blank"&gt;Wiki&lt;/a&gt; を&lt;a href="https://bitbucket.org/pypyja/pypy/wiki/JitFriendliness" target="_blank"&gt;翻訳&lt;/a&gt;しました。以下抜粋します。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;属性名は一定にする: &lt;code&gt;setattr(x, 'a' + some_variable, y)&lt;/code&gt; よりも &lt;code&gt;setattr(x, 'a', y)&lt;/code&gt; の方が高速&lt;/li&gt; &lt;li&gt;新クラス形式を使う / クラスを継承させない&lt;/li&gt; &lt;li&gt;関数の引数の指定で &lt;code&gt;*args&lt;/code&gt; や &lt;code&gt;**kwargs&lt;/code&gt; を使わない: 内部コードが増える&lt;/li&gt; &lt;li&gt;JIT を無効化するコードは書かない: &lt;code&gt;logging&lt;/code&gt; モジュール, トレース, フレームイントロスペクション (&lt;code&gt;sys._getframe()&lt;/code&gt;, &lt;code&gt;sys.exc_info()&lt;/code&gt;          &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;現状は遅いけど改善に取り組んでるコード。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;ジェネレータよりリスト内包表記が高速 -&amp;gt; ジェネレータの高速化&lt;/li&gt; &lt;li&gt;            &lt;code&gt;str.join(list)&lt;/code&gt; より &lt;code&gt;cStringIO&lt;/code&gt; が高速 -&amp;gt; str の高速化&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;チューニングはひたすらベンチマークと格闘のようですね。次は &lt;a href="http://twitter.com/shomah4a" target="_blank" title="@shomah4a"&gt;@shomah4a&lt;/a&gt; 先生です。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-2814002392538206536?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hauMSkLlhDT82_rT9m8jvHacJ8o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hauMSkLlhDT82_rT9m8jvHacJ8o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hauMSkLlhDT82_rT9m8jvHacJ8o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hauMSkLlhDT82_rT9m8jvHacJ8o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=Og48b1pGeSo:HJuG9r8hoBA:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=Og48b1pGeSo:HJuG9r8hoBA:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/Og48b1pGeSo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/2814002392538206536/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/12/pypy-advent-calendar-pypy-maciej.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/2814002392538206536?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/2814002392538206536?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/Og48b1pGeSo/pypy-advent-calendar-pypy-maciej.html" title="PyPy における Python のパフォーマンスチューニング" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-qxQ8KlIfy1k/TugDKcc1YhI/AAAAAAAAHuM/-TJaWvhgxLo/s72-c/jitviewer.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/12/pypy-advent-calendar-pypy-maciej.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcHQX8zeSp7ImA9WhRRF0Q.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-8738560205513754357</id><published>2011-12-02T11:47:00.001+09:00</published><updated>2011-12-02T11:47:10.181+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-02T11:47:10.181+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><title>[memo] Ubuntu 11.10 (kernel 3 系) にアップグレード時の注意書き</title><content type="html">&lt;p&gt;kernel 3 系ではディレクトリツリーが整理されています。しかし、現在のところ Ubuntu 11.10 にアップグレードしても、新ディレクトリツリーに完全に対応してくれません。ちなみに新規インストールの場合は問題ありません。 以下の手順で新ディレクトリツリーに対応します。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;新ディレクトリへ移行&lt;/strong&gt; 
&lt;pre&gt;
sudo mv /var/run/* /run/
sudo mv /var/lock/* /run/lock/
sudo rm -r /var/run
sudo rm -r /var/lock
sudo ln -s /run /var/run
sudo ln -s /run/lock /var/lock
sudo rm /run/dbus/*
&lt;/pre&gt;
 &lt;a href="https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/856810/comments/40" target="_blank" title="Comment 40 for bug 856810"&gt;参考&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;apparmor の権限を更新&lt;/strong&gt; &lt;p&gt;例) /etc/apparmor.d/usr.sbin.mysqld の場合&lt;/p&gt; 
&lt;pre&gt;
---  /var/run/mysqld/mysqld.pid w,
---  /var/run/mysqld/mysqld.sock w,
+++  /{,var/}run/mysqld/mysqld.pid w,
+++  /{,var/}run/mysqld/mysqld.sock w,
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;&lt;strong&gt;その他設定ファイルの見直し&lt;/strong&gt; &lt;p&gt;sock ファイルとか pid ファイルの設定は見直したほうがいいです&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;VMWare 上にインストールしている場合は、ライブラリが競合するので blacklist に以下を追加する。&lt;/p&gt; 
&lt;pre&gt;
# sudo vi /etc/modprobe.d/blacklist.conf
blacklist i2c_piix4
&lt;/pre&gt;
 &lt;p&gt;&lt;a href="http://ubuntuforums.org/showthread.php?t=1099261" target="_blank" title="piix4_smbus host smbus controller not enabled"&gt;参考&lt;/a&gt;&lt;/p&gt; &lt;p&gt;pam が更新されているので、依存してるアプリケーションの更新が大変ですね。。。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-8738560205513754357?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5GT47fn_vlZ8v3Z3Cc3-oG5Ujn4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5GT47fn_vlZ8v3Z3Cc3-oG5Ujn4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5GT47fn_vlZ8v3Z3Cc3-oG5Ujn4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5GT47fn_vlZ8v3Z3Cc3-oG5Ujn4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=Lorwumvjk2g:iZmdKF3pO6U:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=Lorwumvjk2g:iZmdKF3pO6U:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/Lorwumvjk2g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/8738560205513754357/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/12/memo-ubuntu-1110-kernel-3.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/8738560205513754357?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/8738560205513754357?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/Lorwumvjk2g/memo-ubuntu-1110-kernel-3.html" title="[memo] Ubuntu 11.10 (kernel 3 系) にアップグレード時の注意書き" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/12/memo-ubuntu-1110-kernel-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcERns-eSp7ImA9WhRVEUs.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-4176182552425476095</id><published>2011-12-01T20:18:00.001+09:00</published><updated>2012-01-10T10:46:47.551+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-10T10:46:47.551+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="pypy" /><title>PyPy! - PyPy Advend Calendar</title><content type="html">今年も &lt;a href="http://weblog.bulknews.net/post/13584639153/advent-calendars-big-in-japan" target="_blank"&gt;Advent Calendar&lt;/a&gt; の季節が始まりました。この記事は Python を高速化するソリューション &lt;a href="http://atnd.org/events/22078" target="_blank"&gt;PyPy の Advent Calendar&lt;/a&gt;&amp;nbsp;の記事です。最初なので、簡単に PyPy の概要と PyPy-ja のご紹介をしたいと思います。&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; PyPy ってなんなの？&lt;/i&gt;&lt;br /&gt;
&lt;div class="embedly_twitter" id="embedly_twitter_72741128"&gt;
&lt;style type="text/css"&gt;
 #embedly_twitter_72741128{background:url(http://a1.twimg.com/images/themes/theme9/bg.gif) #1A1B1F; padding:20px;} #embedly_twitter_72741128 p{background:#fff;padding:10px 12px 0px 12px;margin:0;min-height:48px;color:#000;font-size:18px;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} #embedly_twitter_72741128 .embedly_tweet_content{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} #embedly_twitter_72741128 p span.metadata{display:block;width:100%;clear:both;margin-top:0px;height:40px; padding-bottom: 12px;} #embedly_twitter_72741128 p span.metadata span.author{line-height:15px;color:#999;font-size:14px} #embedly_twitter_72741128 p span.metadata span.author a{line-height:15px;font-size:20px;vertical-align:middle} #embedly_twitter_72741128 p span.metadata span.author img{float:left;margin:0 10px 0 0px;width:48px;height:48px} #embedly_twitter_72741128 p a {color: #2FC2EF; text-decoration:none;} #embedly_twitter_72741128 p a:hover{text-decoration:underline} #embedly_twitter_72741128 .embedly_timestamp{font-size:13px;display:inline-block;margin-top: 5px;} #embedly_twitter_72741128 .components-above span.embedly_timestamp{font-size:10px;margin-top: 1px;line-height:12px} #embedly_twitter_72741128 a {color: #2FC2EF; text-decoration:none;} #embedly_twitter_72741128 a:hover{text-decoration:underline} #embedly_twitter_72741128 .tweet-screen-name {font-size: 14px; font-weight: bold;} #embedly_twitter_72741128 .tweet-full-name {padding-left: 4px; color: #999; font-size: 12px;} #embedly_twitter_72741128 .tweet-actions{margin-left: 10px;font-size:13px;display:inline-block;width:250px} #embedly_twitter_72741128 .components-above span.tweet-actions{font-size:10px} #embedly_twitter_72741128 .controls{line-height:12px!important} #embedly_twitter_72741128 .tweet-actions a {margin-left:5px} #embedly_twitter_72741128 .tweet-actions a b{font-weight:normal} #embedly_twitter_72741128 .components-above span.tweet-actions a b{vertical-align:baseline;line-height:12px} #embedly_twitter_72741128 .components-above .tweet-text{font-size:13px;vertical-align:baseline} #embedly_twitter_72741128 .tweet-image {float: left; width: 40px;} #embedly_twitter_72741128 .tweet-user-block-image {float: left; width: 48px; height: 48px} #embedly_twitter_72741128 .tweet-row {margin-left: 40px; margin-top: 3px;line-height: 17px;} #embedly_twitter_72741128 .tweet-user-block {margin-left: -40px;} #embedly_twitter_72741128 .stream-item {padding-bottom: 0px; margin-left: 12px;} #embedly_twitter_72741128 .simple-tweet-image img {margin-top: 4px;} #embedly_twitter_72741128 .simple-tweet-content {margin: 0 0 13px 0px; font-size: 14px; min-height:48px;} #embedly_twitter_72741128 .in-reply-to-border {border-color: #EBEBEB; border-style: solid; border-width: 1px 0 0;} #embedly_twitter_72741128 .in-reply-to-text {margin-left: 4px; padding-left: 8px; padding-right: 10px; color: #999; font-size: 12px;} #embedly_twitter_72741128 .tweet-actions i {background: transparent url(http://a2.twimg.com/a/1306889658/phoenix/img/sprite-icons.png) no-repeat;width:15px;height:15px;margin:0 4px -3px 3px;outline: none; text-indent:-99999px;vertical-align:baseline;display:inline-block;position:relative;} #embedly_twitter_72741128 .tweet-actions a.retweet-action i {background-position:-192px 0;} #embedly_twitter_72741128 .tweet-actions a.reply-action i {background-position:0 0;} #embedly_twitter_72741128 .tweet-actions a.favorite-action i {background-position:-32px 0;} 
&lt;/style&gt;&lt;br /&gt;
&lt;div class="embedly_tweet_content"&gt;
&lt;div class="components-middle"&gt;
&lt;span class="metadata"&gt;&lt;span class="author"&gt;&lt;a href="http://twitter.com/nati"&gt;&lt;img src="http://a1.twimg.com/profile_images/1172117736/PB032195_normal.jpg" /&gt;&lt;/a&gt;&lt;b&gt;&lt;a href="http://twitter.com/nati"&gt;@nati&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
nati ueno&lt;/span&gt;&lt;/span&gt; PyPyは日本語で、おっぱいの意味なんだよ　ってUSのpythonやってるエンジニアに教えたら「今日ほどいい日はない！って大喜びしてた」&lt;br /&gt;
&lt;span class="embedly_timestamp"&gt;&lt;a href="http://twitter.com/nati/status/121825143285747713" title="Thu Oct 06 05:52:32 +0000 2011"&gt;Oct 06&lt;/a&gt; via web&lt;/span&gt;&lt;span class="tweet-actions"&gt;&lt;a class="favorite-action" href="https://twitter.com/intent/favorite?tweet_id=121825143285747713" title="Favorite"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Favorite&lt;/b&gt;&lt;/a&gt;&lt;a class="retweet-action" href="https://twitter.com/intent/retweet?tweet_id=121825143285747713" title="Retweet"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Retweet&lt;/b&gt;&lt;/a&gt;&lt;a class="reply-action" href="https://twitter.com/intent/tweet?in_reply_to=121825143285747713" title="Reply"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Reply&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
PyPy は Python 2.7.1 互換の高速な処理系です。現在、着々と py3k 対応の開発も進んでいます。Python 標準処理系である CPython と比較して以下のような特徴があります。&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;速度&lt;/b&gt;: とにかく速いです。JIT パワーです。CPython と PyPy の速度は&lt;a href="http://speed.pypy.org/" target="_blank"&gt;ここ&lt;/a&gt;に公開されています。現在は CPython の 5 倍ぐらい速いですね。特定の環境では Java より速いという&lt;a href="http://blog.liris.org/2011/11/pypy17.html" target="_blank"&gt;計測結果&lt;/a&gt;もあります。ちなみに先日 Win32 環境で同じ計測をしましたが、Win32 環境では pypy 1.6 以降で Java よりも高速という&lt;a href="http://pastebin.com/rva8wZ7t" target="_blank"&gt;結果&lt;/a&gt;がでましたよ。残念ながら 1.7 より 1.6 の方が高速という結果でしたが。。。&lt;/li&gt;
&lt;li&gt;&lt;b&gt;メモリ使用量&lt;/b&gt;: 多い。ほんとにメモリ食います。JIT の作者 Antonio 氏に Python 生みの親の &lt;strike&gt;Guide (oh...)&lt;/strike&gt; Guido 氏が "PyPy の JIT はなんで速いの？" と質問した時に、"オブジェクトが持っているデータをメモリ上の固定位置に配置してるのが効いているみたい" と答えたとのことです (&lt;a href="http://coreblog.org/ats/pypy-is-faster-than-pure-c-code" target="_blank"&gt;ats さんのブログより&lt;/a&gt;)。なるほど。&lt;/li&gt;
&lt;li&gt;&lt;b&gt;互換性&lt;/b&gt;: 一部制限がありますが Python との互換性は高いです。1.7 になってさらに互換性が高まっています。動作する Python ライブラリは&lt;a href="https://bitbucket.org/pypy/compatibility/wiki/Home" target="_blank"&gt;ここ&lt;/a&gt;にまとまっています。"このライブラリも動いたよ！" って方は是非この Wiki を編集してみてください。Django, Flask, Pyramid などのメジャー Web アプリケーションフレームワークや Twisted や Sphinx も動作しますよ！逆に C 拡張を含むライブラリは動作しないものが多いです。1.7 からは numpy も numpypy として動作するようになり、今後対応するライブラリがどんどん増えていきますよ！&lt;/li&gt;
&lt;li&gt;&lt;b&gt;スタックレス&lt;/b&gt;: スタックレスの軽量な擬似的スレッドによる並列処理ができます。&lt;/li&gt;
&lt;/ul&gt;
メモリ最適化して、JIT パワーで、Python 高速化したよってことです。ただ PyPy はそれだけじゃないんです。PyPy は動的言語の処理系を作ることもできます。PyPyPy とかも夢じゃないです。動的言語を作ってみたい方は是非 (この辺は勉強中のため後の方々へ丸投げ)！！&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; PyPy-ja ってなんなの？&lt;/i&gt;&lt;br /&gt;
巷では "PyPy 闇の軍団" と呼ばれています。&lt;strike&gt;あーみんファンクラブです。&lt;/strike&gt;公式ドキュメントの翻訳や PyPy 技術情報の共有等を中心に活動しています。詳細は以下のページを参考にしてください。&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://groups.google.com/group/pypy-ja" target="_blank"&gt;PyPy-ja @ Google Groups&lt;/a&gt;: メーリングリスト&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sites.google.com/site/pypyja/" target="_blank"&gt;PyPy-ja @ Google Sites&lt;/a&gt;: 活動内容等のまとめ&lt;/li&gt;
&lt;li&gt;&lt;a href="http://lingr.com/signup?letmein=pypy_ja" target="_blank"&gt;PyPy-ja @ Lingr&lt;/a&gt;: 公開チャット (Skype チャットの方が盛り上がってます)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bitbucket.org/rokujyouhitoma/pypy/" target="_blank"&gt;翻訳リポジトリ&lt;/a&gt;: ぜひ！&lt;/li&gt;
&lt;li&gt;&lt;a href="http://morepypy-ja.blogspot.com/" target="_blank"&gt;PyPy Status Blog (日本語訳)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Twitter ハッシュタグ: &lt;a href="https://twitter.com/#%21/search?q=%23pypyja" target="_blank"&gt;#pypyja&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
総帥の @rokujouhitoma さんを中心に盛り上がっております。&lt;br /&gt;
&lt;div class="embedly_twitter" id="embedly_twitter_72226868"&gt;
&lt;style type="text/css"&gt;
 #embedly_twitter_72226868{background:url(http://a0.twimg.com/images/themes/theme1/bg.png) #9ae4e8; padding:20px;} #embedly_twitter_72226868 p{background:#fff;padding:10px 12px 0px 12px;margin:0;min-height:48px;color:#000;font-size:18px;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} #embedly_twitter_72226868 .embedly_tweet_content{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} #embedly_twitter_72226868 p span.metadata{display:block;width:100%;clear:both;margin-top:0px;height:40px; padding-bottom: 12px;} #embedly_twitter_72226868 p span.metadata span.author{line-height:15px;color:#999;font-size:14px} #embedly_twitter_72226868 p span.metadata span.author a{line-height:15px;font-size:20px;vertical-align:middle} #embedly_twitter_72226868 p span.metadata span.author img{float:left;margin:0 10px 0 0px;width:48px;height:48px} #embedly_twitter_72226868 p a {color: #0000ff; text-decoration:none;} #embedly_twitter_72226868 p a:hover{text-decoration:underline} #embedly_twitter_72226868 .embedly_timestamp{font-size:13px;display:inline-block;margin-top: 5px;} #embedly_twitter_72226868 .components-above span.embedly_timestamp{font-size:10px;margin-top: 1px;line-height:12px} #embedly_twitter_72226868 a {color: #0000ff; text-decoration:none;} #embedly_twitter_72226868 a:hover{text-decoration:underline} #embedly_twitter_72226868 .tweet-screen-name {font-size: 14px; font-weight: bold;} #embedly_twitter_72226868 .tweet-full-name {padding-left: 4px; color: #999; font-size: 12px;} #embedly_twitter_72226868 .tweet-actions{margin-left: 10px;font-size:13px;display:inline-block;width:250px} #embedly_twitter_72226868 .components-above span.tweet-actions{font-size:10px} #embedly_twitter_72226868 .controls{line-height:12px!important} #embedly_twitter_72226868 .tweet-actions a {margin-left:5px} #embedly_twitter_72226868 .tweet-actions a b{font-weight:normal} #embedly_twitter_72226868 .components-above span.tweet-actions a b{vertical-align:baseline;line-height:12px} #embedly_twitter_72226868 .components-above .tweet-text{font-size:13px;vertical-align:baseline} #embedly_twitter_72226868 .tweet-image {float: left; width: 40px;} #embedly_twitter_72226868 .tweet-user-block-image {float: left; width: 48px; height: 48px} #embedly_twitter_72226868 .tweet-row {margin-left: 40px; margin-top: 3px;line-height: 17px;} #embedly_twitter_72226868 .tweet-user-block {margin-left: -40px;} #embedly_twitter_72226868 .stream-item {padding-bottom: 0px; margin-left: 12px;} #embedly_twitter_72226868 .simple-tweet-image img {margin-top: 4px;} #embedly_twitter_72226868 .simple-tweet-content {margin: 0 0 13px 0px; font-size: 14px; min-height:48px;} #embedly_twitter_72226868 .in-reply-to-border {border-color: #EBEBEB; border-style: solid; border-width: 1px 0 0;} #embedly_twitter_72226868 .in-reply-to-text {margin-left: 4px; padding-left: 8px; padding-right: 10px; color: #999; font-size: 12px;} #embedly_twitter_72226868 .tweet-actions i {background: transparent url(http://a2.twimg.com/a/1306889658/phoenix/img/sprite-icons.png) no-repeat;width:15px;height:15px;margin:0 4px -3px 3px;outline: none; text-indent:-99999px;vertical-align:baseline;display:inline-block;position:relative;} #embedly_twitter_72226868 .tweet-actions a.retweet-action i {background-position:-192px 0;} #embedly_twitter_72226868 .tweet-actions a.reply-action i {background-position:0 0;} #embedly_twitter_72226868 .tweet-actions a.favorite-action i {background-position:-32px 0;} 
&lt;/style&gt;&lt;br /&gt;
&lt;div class="embedly_tweet_content"&gt;
&lt;div class="components-middle"&gt;
&lt;span class="metadata"&gt;&lt;span class="author"&gt;&lt;a href="http://twitter.com/rokujyouhitoma"&gt;&lt;img src="http://a0.twimg.com/profile_images/1590563319/ike_normal.jpg" /&gt;&lt;/a&gt;&lt;b&gt;&lt;a href="http://twitter.com/rokujyouhitoma"&gt;@rokujyouhitoma&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
Tohru Ike&lt;/span&gt;&lt;/span&gt; pypy闇の軍団の総帥です。こんにちわこんにちわ。&lt;br /&gt;
&lt;span class="embedly_timestamp"&gt;&lt;a href="http://twitter.com/rokujyouhitoma/status/134071737611599873" title="Wed Nov 09 00:56:07 +0000 2011"&gt;Nov 09&lt;/a&gt; via &lt;a href="http://sites.google.com/site/yorufukurou/" rel="nofollow"&gt;YoruFukurou&lt;/a&gt;&lt;/span&gt;&lt;span class="tweet-actions"&gt;&lt;a class="favorite-action" href="https://twitter.com/intent/favorite?tweet_id=134071737611599873" title="Favorite"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Favorite&lt;/b&gt;&lt;/a&gt;&lt;a class="retweet-action" href="https://twitter.com/intent/retweet?tweet_id=134071737611599873" title="Retweet"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Retweet&lt;/b&gt;&lt;/a&gt;&lt;a class="reply-action" href="https://twitter.com/intent/tweet?in_reply_to=134071737611599873" title="Reply"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Reply&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="embedly_twitter" id="embedly_twitter_32610414"&gt;
&lt;style type="text/css"&gt;
 #embedly_twitter_32610414{background:url(http://a0.twimg.com/images/themes/theme1/bg.png) #9ae4e8; padding:20px;} #embedly_twitter_32610414 p{background:#fff;padding:10px 12px 0px 12px;margin:0;min-height:48px;color:#000;font-size:18px;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} #embedly_twitter_32610414 .embedly_tweet_content{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} #embedly_twitter_32610414 p span.metadata{display:block;width:100%;clear:both;margin-top:0px;height:40px; padding-bottom: 12px;} #embedly_twitter_32610414 p span.metadata span.author{line-height:15px;color:#999;font-size:14px} #embedly_twitter_32610414 p span.metadata span.author a{line-height:15px;font-size:20px;vertical-align:middle} #embedly_twitter_32610414 p span.metadata span.author img{float:left;margin:0 10px 0 0px;width:48px;height:48px} #embedly_twitter_32610414 p a {color: #0000ff; text-decoration:none;} #embedly_twitter_32610414 p a:hover{text-decoration:underline} #embedly_twitter_32610414 .embedly_timestamp{font-size:13px;display:inline-block;margin-top: 5px;} #embedly_twitter_32610414 .components-above span.embedly_timestamp{font-size:10px;margin-top: 1px;line-height:12px} #embedly_twitter_32610414 a {color: #0000ff; text-decoration:none;} #embedly_twitter_32610414 a:hover{text-decoration:underline} #embedly_twitter_32610414 .tweet-screen-name {font-size: 14px; font-weight: bold;} #embedly_twitter_32610414 .tweet-full-name {padding-left: 4px; color: #999; font-size: 12px;} #embedly_twitter_32610414 .tweet-actions{margin-left: 10px;font-size:13px;display:inline-block;width:250px} #embedly_twitter_32610414 .components-above span.tweet-actions{font-size:10px} #embedly_twitter_32610414 .controls{line-height:12px!important} #embedly_twitter_32610414 .tweet-actions a {margin-left:5px} #embedly_twitter_32610414 .tweet-actions a b{font-weight:normal} #embedly_twitter_32610414 .components-above span.tweet-actions a b{vertical-align:baseline;line-height:12px} #embedly_twitter_32610414 .components-above .tweet-text{font-size:13px;vertical-align:baseline} #embedly_twitter_32610414 .tweet-image {float: left; width: 40px;} #embedly_twitter_32610414 .tweet-user-block-image {float: left; width: 48px; height: 48px} #embedly_twitter_32610414 .tweet-row {margin-left: 40px; margin-top: 3px;line-height: 17px;} #embedly_twitter_32610414 .tweet-user-block {margin-left: -40px;} #embedly_twitter_32610414 .stream-item {padding-bottom: 0px; margin-left: 12px;} #embedly_twitter_32610414 .simple-tweet-image img {margin-top: 4px;} #embedly_twitter_32610414 .simple-tweet-content {margin: 0 0 13px 0px; font-size: 14px; min-height:48px;} #embedly_twitter_32610414 .in-reply-to-border {border-color: #EBEBEB; border-style: solid; border-width: 1px 0 0;} #embedly_twitter_32610414 .in-reply-to-text {margin-left: 4px; padding-left: 8px; padding-right: 10px; color: #999; font-size: 12px;} #embedly_twitter_32610414 .tweet-actions i {background: transparent url(http://a2.twimg.com/a/1306889658/phoenix/img/sprite-icons.png) no-repeat;width:15px;height:15px;margin:0 4px -3px 3px;outline: none; text-indent:-99999px;vertical-align:baseline;display:inline-block;position:relative;} #embedly_twitter_32610414 .tweet-actions a.retweet-action i {background-position:-192px 0;} #embedly_twitter_32610414 .tweet-actions a.reply-action i {background-position:0 0;} #embedly_twitter_32610414 .tweet-actions a.favorite-action i {background-position:-32px 0;} 
&lt;/style&gt;&lt;br /&gt;
&lt;div class="embedly_tweet_content"&gt;
&lt;div class="components-middle"&gt;
&lt;span class="metadata"&gt;&lt;span class="author"&gt;&lt;a href="http://twitter.com/rokujyouhitoma"&gt;&lt;img src="http://a0.twimg.com/profile_images/1590563319/ike_normal.jpg" /&gt;&lt;/a&gt;&lt;b&gt;&lt;a href="http://twitter.com/rokujyouhitoma"&gt;@rokujyouhitoma&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
Tohru Ike&lt;/span&gt;&lt;/span&gt; こわくないよ。全然こわくないよ。 RT &lt;a href="http://twitter.com/shomah4a"&gt;@shomah4a&lt;/a&gt;: 総帥こわーい [11時18分24秒 JST] Toru Ike(rokujyouhitoma, Tohru Ike): まだビルドしたことないの？( ﾟдﾟ)､ﾍﾟｯ &lt;a href="http://search.twitter.com/search?q=%23pypyja"&gt;#pypyja&lt;/a&gt;&lt;br /&gt;
&lt;span class="embedly_timestamp"&gt;&lt;a href="http://twitter.com/rokujyouhitoma/status/138520660019380225" title="Mon Nov 21 07:34:33 +0000 2011"&gt;Nov 21&lt;/a&gt; via &lt;a href="http://sites.google.com/site/yorufukurou/" rel="nofollow"&gt;YoruFukurou&lt;/a&gt;&lt;/span&gt;&lt;span class="tweet-actions"&gt;&lt;a class="favorite-action" href="https://twitter.com/intent/favorite?tweet_id=138520660019380225" title="Favorite"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Favorite&lt;/b&gt;&lt;/a&gt;&lt;a class="retweet-action" href="https://twitter.com/intent/retweet?tweet_id=138520660019380225" title="Retweet"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Retweet&lt;/b&gt;&lt;/a&gt;&lt;a class="reply-action" href="https://twitter.com/intent/tweet?in_reply_to=138520660019380225" title="Reply"&gt;&lt;i&gt;&lt;/i&gt;&lt;b&gt;Reply&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
ご興味ごおありの方は是非コミュニティに参加してください。1 人でも多くの PyPy ユーザが増えるといいなーと思ってます。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-4176182552425476095?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4W82FYObh2mVSOiXsvoLTqDf_YM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4W82FYObh2mVSOiXsvoLTqDf_YM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4W82FYObh2mVSOiXsvoLTqDf_YM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4W82FYObh2mVSOiXsvoLTqDf_YM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=f0aRMd35mKI:ATvs8mFBD2Y:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=f0aRMd35mKI:ATvs8mFBD2Y:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/f0aRMd35mKI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/4176182552425476095/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/12/advent-calendar-python-pypy-advent.html#comment-form" title="2 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/4176182552425476095?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/4176182552425476095?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/f0aRMd35mKI/advent-calendar-python-pypy-advent.html" title="PyPy! - PyPy Advend Calendar" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://surgo.jp/2011/12/advent-calendar-python-pypy-advent.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04MQ38yfCp7ImA9WhdXEEU.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-7377066498061307497</id><published>2011-08-23T15:19:00.001+09:00</published><updated>2011-08-23T15:46:22.194+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-23T15:46:22.194+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="pyside" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>PySide チュートリアル - helloworld から ユニットテストまで</title><content type="html">&lt;p&gt;ここ 2 ヶ月ほど &lt;a href="http://www.pyside.org/" target="_blank" title="PySide"&gt;PySide&lt;/a&gt; でお仕事してました。もともと PyQt で動いてたアプリケーションだったのですが、けっこう仕様変更が大きかったこともあり、どうせなので PySide で作り直してみることにしました。両フレームワークの差異は&lt;a href="http://developer.qt.nokia.com/wiki/Differences_Between_PySide_and_PyQt" target="_blank" title="Differences Between PySide and PyQt"&gt;このページ&lt;/a&gt;にまとまっています (&lt;a href="http://d.hatena.ne.jp/doloopwhile/20110207/1297075318" target="_blank" title="PySide と PyQt の差異"&gt;id:doloopwhile&lt;/a&gt; さんが翻訳されています)。大きくは、&lt;/p&gt; &lt;ul&gt; &lt;li&gt;モジュール名が PyQt から PySide に&lt;/li&gt; &lt;li&gt;PyQt の API は QString や QVariants 等 Qt が提供する型と、unicode 等 Python のデータ型の両方をサポートしていましたが、PySide では Python のデータ型のみをサポート&lt;/li&gt; &lt;li&gt;画像等のリソースファイルをバイナリに変換したりするツール類の名称がそれぞれ変更&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;pyuic4 -&amp;gt; pyside-uic&lt;/li&gt; &lt;li&gt;pyrcc4 -&amp;gt; pyside-rcc4&lt;/li&gt; &lt;li&gt;pylupdate4 -&amp;gt; pyside-lupdate&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;PySide への変更はそんなに問題ではありませんが、まだ開発中ということもあり、pyside-rcc4 にバグがあったり、&lt;a href="http://tcha.org/blog/2011/07/16/pyside-signal-benchmark/" target="_blank" title="PySide の Signal-Slot は PyQt より遅い"&gt;signal-slot&lt;/a&gt; が遅いということもあるようです。この辺りは今後に期待です。&lt;/p&gt; &lt;p&gt;ということで自分の復習 &amp;amp; メモと、PySide がちょっとでも普及すればいいなということで、PySide のチュートリアルを作ってみました。helloworld ということで、ボタンをおしたらテキストボックスに "Hello world" と表示するだけのなんの面白味もないウィジェットと、そのユニットテストを作ってみます。ソースは &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/" target="_blank" title="helloworld"&gt;bitbucket&lt;/a&gt; に公開しました。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;環境を整える &lt;dl&gt; &lt;dt&gt;インストールするもの&lt;/dt&gt; &lt;dd&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.python.org/download/" target="_blank" title="Download Python"&gt;Python&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://sourceforge.net/projects/pywin32/files/pywin32/" target="_blank" title="Python for Windows extensions"&gt;Python for Windows extensions&lt;/a&gt; (Windows ユーザのみ)&lt;/li&gt; &lt;li&gt;&lt;a href="http://developer.qt.nokia.com/wiki/Category:LanguageBindings::PySide::Downloads" target="_blank" title="PySide Downloads"&gt;PySide&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/dd&gt; &lt;dt&gt;推奨&lt;/dt&gt; &lt;dd&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://pypi.python.org/pypi/virtualenv" target="_blank" title="Virtual Python Environment builder"&gt;virtualenv&lt;/a&gt; - py2exe でフリージング (実行ファイル形式に変換) する際に余計なライブラリが含まれるのを防ぐため&lt;/li&gt; &lt;/ul&gt; &lt;/dd&gt; &lt;/dl&gt; &lt;/li&gt; &lt;li&gt;ウィジェットを表示してみる &lt;br/&gt;Python インタプリタから以下のように打つと、ダイアログを表示することができます。 
&lt;pre class="prettyprint"&gt;
import sys
from PySide import QtGui
app = QtGui.QApplication(sys.argv)
dialog = QtGui.QDialog()
dialog.exec_()
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;UI を作る &lt;br/&gt;今回作る helloworld アプリケーションはテキストボックスとボタンのみのウィジェットです。 サンプルコードの &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-21" target="_blank" title="setup_ui"&gt;setup_ui&lt;/a&gt; の部分で UI を設定しています。 Qt デザイナと pyside-uic を使う方法もありますが、私は使ったことがないです。。。UI を作っていくポイントを抜粋すると、 &lt;ul&gt; &lt;li&gt;各ウィジェット (QWidget 及びサブクラス) に、レイアウト (QLayout のサブクラス) を設定する &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.pyside.org/docs/pyside/PySide/QtGui/QVBoxLayout.html" target="_blank" title="QVBoxLayout"&gt;QVBoxLayout&lt;/a&gt;: 縦に配列していく&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.pyside.org/docs/pyside/PySide/QtGui/QHBoxLayout.html" target="_blank" title="QHBoxLayout"&gt;QHBoxLayout&lt;/a&gt;: 横に配列していく&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.pyside.org/docs/pyside/PySide/QtGui/QGridLayout.html" target="_blank" title="QGridLayout"&gt;QGridLayout&lt;/a&gt;: グリッド状に配列していく&lt;/li&gt; &lt;li&gt;他にも &lt;a href="http://www.pyside.org/docs/pyside/PySide/QtGui/QFormLayout.html" target="_blank" title="QFormLayout"&gt;QFormLayout&lt;/a&gt; や &lt;a href="http://www.pyside.org/docs/pyside/PySide/QtGui/QStackedLayout.html" target="_blank" title="QStackedLayout"&gt;QStackedLayout&lt;/a&gt; 等があります&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;各レイアウトに子供のウィジェットを追加していく&lt;/li&gt; &lt;li&gt;ウィジェットをネストさせることで、より複雑な UI も表現できます&lt;/li&gt; &lt;/ul&gt; UI と併せて、クラスのインターフェースも実装します。Python の property を利用してもいいですが、Qt にも QtCore.Property が用意されています。異なる点は、 &lt;ul&gt; &lt;li&gt;型を明示する&lt;/li&gt; &lt;li&gt;settar が呼び出された後に signal を送出することができる (Python の property で書いて、setattr 時に emit しちゃってもいいけど・・・)&lt;/li&gt; &lt;/ul&gt; です。可能であれば、QtCore の Property で実装しちゃいましょう。サンプルコードでは &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-55" target="_blank" title="text"&gt;text&lt;/a&gt; をプロパティ化しています。変更された際に通知する signal は &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-11" target="_blank" title="text"&gt;text_changed&lt;/a&gt; として登録しています。&lt;/li&gt; &lt;li&gt;ユニットテストを書く &lt;br/&gt;UI ができたら、ユニットテストを書きます (テストファースト :-)。Qt には &lt;a href="http://www.pyside.org/docs/pyside/PySide/QtTest/index.html" target="_blank" title="PySide.QtTest"&gt;QtTest&lt;/a&gt; というテスト用のフレームワークが用意されています。PySide では、&lt;a href="http://www.pyside.org/docs/pyside/PySide/QtTest/index.html" target="_blank" title="PySide.QtTest"&gt;このページ&lt;/a&gt;にも記載されているように、Python の unittest モジュールを使ってユニットテストします。Qt はテストも signal-slot ベースです。ウィジェットにある signal が創出され、slot が処理した後に、ウィジェットがどうなっているか。&lt;a href="http://www.pyside.org/docs/pyside/PySide/QtTest/QTest.html" target="_blank" title="QTest"&gt;QTest&lt;/a&gt; にいくつかの基本的なイベントを発生させるメソッドが用意されています。&lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/test.py#cl-17" target="_blank" title="test_button_clicked"&gt;サンプルコード&lt;/a&gt;ではボタンをクリックした際のテキストボックスの状態をテストしています。まだ signal-slot を実装していないので、テストは失敗するはず。&lt;/li&gt; &lt;li&gt;イベント (signal-slot) を実装する &lt;br/&gt;ユニットテストを通過できるように signal-slot を実装していきます。signal-slot の書き方は&lt;a href="http://developer.qt.nokia.com/wiki/Signals_and_Slots_in_PySide" target="_blank" title="Signals and Slots in PySide"&gt;何種類かあります&lt;/a&gt;。サンプルコードの &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-38" target="_blank" title="setup_events"&gt;setup_events&lt;/a&gt; の箇所でイベントをセットアップしています。ここに connect をたくさん書いてもいいですが、子ウィジェットのイベントを再帰的にコネクトする &lt;a href="http://www.pyside.org/docs/pyside/PySide/QtCore/QMetaObject.html#PySide.QtCore.PySide.QtCore.QMetaObject.connectSlotsByName" target="_blank" title="PySide.QtCore.QMetaObject.connectSlotsByName"&gt;connectSlotsByName&lt;/a&gt; を指定するのが好きです。コード量が少なくなるのでこの書き方を多用しています (イベントハンドラの追加をするたびに connect とか書きたくない)。 &lt;br/&gt;connectSlotsByName を利用すると、slot メソッドを &lt;code class="prettyprint"&gt;def on_&amp;lt;object name&amp;gt;_&amp;lt;signal name&amp;gt;(&amp;lt;signal parameters&amp;gt;)&lt;/code&gt; という風に書けるようになります。 この object name は、各子ウィジェットに対し setObjectname で指定してあげる必要があります。サンプルコードでは、&lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-26" target="_blank" title="setObjectName"&gt;base_layout&lt;/a&gt;, &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-31" target="_blank" title="setObjectName"&gt;lineedit&lt;/a&gt;, &lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-35" target="_blank" title="setObjectName"&gt;button&lt;/a&gt; すべてにセットしていますが、今回の要件を満たすには button ウィジェットだけセットすればいいです。これでサンプルコードのように &lt;code class="prettyprint"&gt;&lt;a href="https://bitbucket.org/Surgo/pyside-tutorials/src/tip/helloworld/helloworld.py#cl-57" target="_blank" title="on_button_clicked"&gt;on_button_clicked&lt;/a&gt;&lt;/code&gt; で button の clicked イベントの slot を作成できます。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;以上、なんの面白くもないチュートリアルですが、 PySide での開発の流れが少しでも見えたら良いかなーと。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-7377066498061307497?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Qw9dRkkPr7wv2hVcTWMCau31dsg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Qw9dRkkPr7wv2hVcTWMCau31dsg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Qw9dRkkPr7wv2hVcTWMCau31dsg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Qw9dRkkPr7wv2hVcTWMCau31dsg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=RH-krcHb6Fo:9mM3KHXLCUk:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=RH-krcHb6Fo:9mM3KHXLCUk:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/RH-krcHb6Fo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/7377066498061307497/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/08/pyside-helloworld.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7377066498061307497?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7377066498061307497?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/RH-krcHb6Fo/pyside-helloworld.html" title="PySide チュートリアル - helloworld から ユニットテストまで" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/08/pyside-helloworld.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8EQHw5fip7ImA9WhdRGE0.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-7936391810650226520</id><published>2011-08-08T20:59:00.000+09:00</published><updated>2011-08-08T21:00:01.226+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-08T21:00:01.226+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="win32" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="windows" /><title>Python で Windows のプリンタスプールを削除する</title><content type="html">&lt;p&gt;&lt;a href="http://support.microsoft.com/kb/946737" target="_blank" title="http://support.microsoft.com/kb/946737"&gt;Windows XP で印刷をキャンセルしたり、印刷キューに残っている印刷ジョブを削除したりする方法 (KB946737)&lt;/a&gt; のメモ&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
import os
import win32serviceutil

# スプールファイルの保存先
spooled_dir = os.path.join(
        os.environ.get('SYSTEMROOT', r'C:\WINDOWS'),
        'system32', 'spool', 'printers', )
win32serviceutil.StopService('spooler')
for f in os.listdir(spooled_dir):
    os.remove(os.path.join(spooled_dir, f))
win32serviceutil.StartService('spooler')
&lt;/pre&gt;
 &lt;p&gt;StopService の後もプロセスがしばらくファイルをつかんじゃって消せない場合もある&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-7936391810650226520?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nsl28EnGtB4JY2POuwebAObqJi8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nsl28EnGtB4JY2POuwebAObqJi8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nsl28EnGtB4JY2POuwebAObqJi8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nsl28EnGtB4JY2POuwebAObqJi8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=Xb3ga0l0WQc:va84UUASxfw:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=Xb3ga0l0WQc:va84UUASxfw:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/Xb3ga0l0WQc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/7936391810650226520/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/08/python-windows.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7936391810650226520?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7936391810650226520?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/Xb3ga0l0WQc/python-windows.html" title="Python で Windows のプリンタスプールを削除する" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/08/python-windows.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQNQn0zeSp7ImA9WhZaEUk.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-1615092210254408871</id><published>2011-06-26T14:49:00.001+09:00</published><updated>2011-06-27T11:39:53.381+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-27T11:39:53.381+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dotcloud" /><title>dotcloud いいね！環境編</title><content type="html">&lt;p&gt;引き続き dotcloud。環境の私的覚書など。途中 (必要になったら書くかも)。&lt;/p&gt; &lt;dl&gt; &lt;dt&gt;CPU&lt;/dt&gt; &lt;dd&gt;Intel(R) Xeon(R) CPU - X5550 @ 2.67GHz * 4　(&lt;a href="https://gist.github.com/1047271" target="_blank" title="cpuinfo"&gt;/proc/cpuinfo&lt;/a&gt;)&lt;/dd&gt; &lt;dt&gt;メモリ&lt;/dt&gt; &lt;dd&gt;35031888 kB　(&lt;a href="https://gist.github.com/1047275" target="_blank" title="meminfo"&gt;/proc/meminfo&lt;/a&gt;)&lt;/dd&gt; &lt;dt&gt;ディスク&lt;/dt&gt; &lt;dd&gt; 
&lt;pre&gt;
Filesystem           1K-blocks      Used Available Use% Mounted on
rootfs               1056888712  66780428 936421464   7% /
none                 1056888712  66780428 936421464   7% /
/dev/sdh1            1056888712  66780428 936421464   7% /home/dotcloud
varrun                    4096        32      4064   1% /var/run
varlock                   1024         0      1024   0% /var/lock
shm                      65536         0     65536   0% /dev/shm
&lt;/pre&gt;
&lt;/dd&gt; &lt;dt&gt;OS&lt;/dt&gt; &lt;dd&gt;debian 6.0 - squeeze/sid (sid ?!)&lt;/dd&gt; &lt;dd&gt;Linux version 2.6.38.2-grsec-dotcloud-ec2 (root@ebichu) (gcc version 4.3.2 (Debian 4.3.2-1.1) )&lt;/dd&gt; &lt;dt&gt;Java&lt;/dt&gt; &lt;dd&gt;Java(TM) SE Runtime Environment (build 1.6.0_24-b07)&lt;/dd&gt; &lt;dd&gt;Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)&lt;/dd&gt; &lt;dd&gt; &lt;dl&gt; &lt;dt&gt;Jetty&lt;/dt&gt; &lt;dd&gt;jetty-6.1.22&lt;/dd&gt; &lt;/dl&gt; &lt;/dd&gt; &lt;dt&gt;Python&lt;/dt&gt; &lt;dd&gt;Python 2.6.5&lt;/dd&gt; &lt;dd&gt; &lt;dl&gt; &lt;dt&gt;ライブラリ (/usr/lib/python2.6/dist-packages)&lt;/dt&gt; &lt;dd&gt; &lt;ul&gt; &lt;li&gt;ANSI&lt;/li&gt; &lt;li&gt;debconf&lt;/li&gt; &lt;li&gt;duplicity&lt;/li&gt; &lt;li&gt;fdpexpect&lt;/li&gt; &lt;li&gt;FSM&lt;/li&gt; &lt;li&gt;pexpect&lt;/li&gt; &lt;li&gt;pxssh&lt;/li&gt; &lt;li&gt;screen&lt;/li&gt; &lt;/ul&gt; &lt;/dd&gt; &lt;/dl&gt; &lt;/dd&gt; &lt;dt&gt;MongoDB&lt;/dt&gt; &lt;dt&gt;MySQL&lt;/dt&gt; &lt;dt&gt;Node.js&lt;/dt&gt; &lt;dt&gt;Perl&lt;/dt&gt; &lt;dt&gt;PHP&lt;/dt&gt; &lt;dd&gt;&lt;a href="http://d3dd6107.dotcloud.com/" target="_blank" title="phpinfo"&gt;phpinfo&lt;/a&gt;&lt;/dd&gt; &lt;dt&gt;PostgreSQL&lt;/dt&gt; &lt;dt&gt;Redis&lt;/dt&gt; &lt;dt&gt;Ruby&lt;/dt&gt; &lt;dt&gt;SMTP&lt;/dt&gt; &lt;dt&gt;Solr&lt;/dt&gt; &lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-1615092210254408871?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aMDmtYZm0BLgmwHFc5rPKo454tU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aMDmtYZm0BLgmwHFc5rPKo454tU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aMDmtYZm0BLgmwHFc5rPKo454tU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aMDmtYZm0BLgmwHFc5rPKo454tU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=7kXc87TAd1E:sWKYQp5lIY8:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=7kXc87TAd1E:sWKYQp5lIY8:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/7kXc87TAd1E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/1615092210254408871/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/06/dotcloud.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/1615092210254408871?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/1615092210254408871?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/7kXc87TAd1E/dotcloud.html" title="dotcloud いいね！環境編" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/06/dotcloud.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcHQno4fip7ImA9WhVVF00.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-1481878900166193589</id><published>2011-06-26T12:52:00.001+09:00</published><updated>2012-05-11T11:07:13.436+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-11T11:07:13.436+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dotcloud" /><title>dotcloud いいね！jenkins 編</title><content type="html">&lt;p&gt;&lt;ins&gt;2012/05/11 更新: &lt;a href="http://surgo.jp/2012/05/jenkins-on-dotcloud.html" target="_blank" title="Jenkins on dotCloud"&gt;こっち&lt;/a&gt;の方が簡単&lt;/ins&gt;&lt;/p&gt; &lt;p&gt;プライベートなコードは github, bitbucket などなどのオンライン &lt;abbr title="Version control systems"&gt;VCS&lt;/abbr&gt; にホスティングしてますが、&lt;abbr title="continuous integration"&gt;CI&lt;/abbr&gt; もホスティングできないかなーと。そこで &lt;a href="http://www.dotcloud.com/" target="_blank" title="dotCloud"&gt;dotcloud&lt;/a&gt; ですよ！しばらく招待待ちでしたけど、今は普通に signup できるようになってます (beta から cli が結構変わってる...) 。&lt;/p&gt; &lt;p&gt;cli のセットアップとかは&lt;a href="http://docs.dotcloud.com/#installation.html" target="_blank" title="Installing the CLI"&gt;本家ドキュメント&lt;/a&gt;に載ってるし、いろんな&lt;a href="http://www.google.com/search?q=dotcloud+cli+install" target="_blank" title="dotcloud cli install - google"&gt;ブログ&lt;/a&gt;に載ってます。ただファイル転送が rsync ベースなので win ユーザは cygwin いれたりちょっとめんどい。speier さんが win 用 cli のインストーラを &lt;a href="https://github.com/speier/DotCloudWin" target="_blank" title="DotCloudWin"&gt;github&lt;/a&gt; に公開されてる (多謝) ので使うといいと思います。&lt;del&gt;でも動かないので、パッチを当ててコンパイルしたのを &lt;a href="http://db.tt/WZkBz1Q" target="_blank" title="dotjenkins"&gt;dropbox&lt;/a&gt; 上においてます。speier さんのやつをインストール後、dotcloud.exe を入れ替えてください。&lt;/del&gt; &lt;ins&gt;マージしていただきました。ありがとうございます。&lt;/ins&gt;&lt;/p&gt; &lt;p&gt;dotcloud の java サーブレットコンテナは &lt;a href="http://jetty.codehaus.org/jetty/" target="_blank" title="jetty"&gt;jetty&lt;/a&gt; です。jenkins を jetty にデプロイする場合は &lt;code&gt;JENKINS_HOME&lt;/code&gt; を設定しないと動きませぬ (&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Jetty" target="_blank" title="Jenkins &gt;Containers &gt; Jetty"&gt;参考&lt;/a&gt;)。あたりまえですが、dotcloud の &lt;code&gt;/etc/jetty/jetty.xml&lt;/code&gt; の書き換えなんてできません。&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Upgrading+from+Hudson+to+Jenkins#UpgradingfromHudsontoJenkins-Installedinservletcontainer" target="_blank" title="Upgrading from Hudson to Jenkins"&gt;ここ&lt;/a&gt;をみて、なんとかホームディレクトリを変更しようと web.xml とか書き換えてみたんですけど、 dotcloud 上 (jetty 上?) じゃ動きませんでした。。。なので、jenkins が dotcloud で動作するよう &lt;a href="https://github.com/Surgo/jenkins" target="_blank" title="jenkins"&gt;fork&lt;/a&gt; しました。&lt;code&gt;/home/dotcloud&lt;/code&gt; ってディレクトリがあったら &lt;code&gt;/home/dotcloud/jetty/.jenkins&lt;/code&gt; ってのを &lt;code&gt;JENKINS_HOME&lt;/code&gt; にするようにしただけです。いちおう&lt;a href="http://ci.surgo.dotcloud.com/" target="_blank" title="jenkins"&gt;ここ&lt;/a&gt;で動かしています (ログインが必要ですｗ)。war は同じく &lt;a href="http://db.tt/WZkBz1Q" target="_blank" title="dotjenkins"&gt;dropbox&lt;/a&gt; 上においてますので、使いたい方はぜひ。&lt;/p&gt; &lt;p&gt;インストール方法&lt;/p&gt; &lt;ol&gt; &lt;li&gt;プロジェクトディレクトリの作成 
&lt;pre&gt;
mkdir &amp;lt;dotjenkins&amp;gt;
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;プロジェクトディレクトリに jenkins.war を入れる &lt;p&gt;&lt;code&gt;http://&amp;lt;dotjenkins&amp;gt;.dotcloud.com/jenkins&lt;/code&gt; ではなく &lt;code&gt;http://&amp;lt;dotjenkins&amp;gt;.dotcloud.com/&lt;/code&gt; でアクセスできるようにしたい場合は ROOT.jar に名前を変えておく (&lt;a href="http://docs.dotcloud.com/#java.html" target="_blank" title="Java"&gt;参考&lt;/a&gt;)。&lt;/p&gt; &lt;/li&gt; &lt;li&gt;dotcloud プロジェクトの作成 
&lt;pre&gt;
dotcloud create &amp;lt;dotjenkins&amp;gt;
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;&lt;code&gt;dotcloud.yml&lt;/code&gt; (環境設定ファイル) の編集 
&lt;pre&gt;
www:
  type: java
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;デプロイ 
&lt;pre&gt;
dotcloud push &amp;lt;dotjenkins&amp;gt; &amp;lt;./path/to/project_dir&amp;gt;
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;&lt;code&gt;JENKINS_HOME&lt;/code&gt; ディレクトリの作成 
&lt;pre&gt;
dotcloud run &amp;lt;dotjenkins&amp;gt;.www -- mkdir jetty
&lt;/pre&gt;
&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;これで CI もホスティングできました。プラグインとかいじれば bitbucket や github ともスムーズに連携できます。これで幸せプライベートコーディングができますｗ&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-1481878900166193589?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TrdYy6L8Q2Cf4zJ9VNLGSjoeNp0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TrdYy6L8Q2Cf4zJ9VNLGSjoeNp0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TrdYy6L8Q2Cf4zJ9VNLGSjoeNp0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TrdYy6L8Q2Cf4zJ9VNLGSjoeNp0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=swSmEI46nok:mJKrGVJmms4:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=swSmEI46nok:mJKrGVJmms4:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/swSmEI46nok" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/1481878900166193589/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/06/dotcloud-jenkins.html#comment-form" title="1 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/1481878900166193589?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/1481878900166193589?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/swSmEI46nok/dotcloud-jenkins.html" title="dotcloud いいね！jenkins 編" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://surgo.jp/2011/06/dotcloud-jenkins.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcBSHg-cSp7ImA9WhZVGE4.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-6288454241797630679</id><published>2011-05-31T17:43:00.001+09:00</published><updated>2011-05-31T17:54:19.659+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-31T17:54:19.659+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Python 環境構築メモ (2.6 系)</title><content type="html">&lt;p&gt;&lt;strong&gt;環境構築&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Python 2.6 系 (&lt;a href="http://www.python.org/download/releases/2.6.6/" target="_blank" title="Python 2.6.6"&gt;2.6.6&lt;/a&gt; - 2011-05-31 現在) をインストール &lt;br/&gt;※ Windows の場合 &lt;ul&gt; &lt;li&gt;&lt;a href="http://sourceforge.net/projects/pywin32/files/pywin32/" target="_blank" title="pywin32"&gt;pywin32&lt;/a&gt; をインストール&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.microsoft.com/japan/msdn/vstudio/2008/product/express/" target="_blank" title="Visual Studio 2008 Express Edition"&gt;Visual C++ 2008 Express Edition&lt;/a&gt; をインストールし、Path に"&lt;code&gt;C:\Program Files\Microsoft Visual Studio 9.0\VC&lt;/code&gt;" を追加する&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href="http://pypi.python.org/pypi/distribute" target="_blank" title="distribute"&gt;distribute&lt;/a&gt; をインストール 
&lt;pre&gt;
# Linux
curl -O http://python-distribute.org/distribute_setup.py
python distribute_setup.py
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;必要であれば &lt;a href="http://ipython.scipy.org/" target="_blank" title="IPython"&gt;ipython&lt;/a&gt; 等共通にしておきたいライブラリをインストール 
&lt;pre&gt;
easy_install -U ipython PyReadline
&lt;/pre&gt;
 参考: &lt;a href="http://www.ianlewis.org/jp/ipython-virtualenv" target="_blank" title="ipython と virtualenv を同時に使う方法"&gt;ipython と virtualenv を同時に使う方法&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://pypi.python.org/pypi/virtualenv/" target="_blank" title="virtualenv"&gt;virtualenv&lt;/a&gt;, &lt;a href="http://pypi.python.org/pypi/virtualenvwrapper/" target="_blank" title="virtualenvwrapper"&gt;virtualenvwrapper&lt;/a&gt; をインストール 
&lt;pre&gt;
easy_install -U virtualenvwrapper
&lt;/pre&gt;
 Windows の場合は、 &lt;a href="https://github.com/davidmarble/virtualenvwrapper-win" target="_blank" title="virtualenvwrapper-win"&gt;virtualenvwrapper-win&lt;/a&gt; を \path\to\Python26\Scripts に保存する&lt;/li&gt; &lt;li&gt;プロジェクト毎のvirtualenv を作成 
&lt;pre&gt;
mkvirtualenv &amp;lt;name&amp;gt;
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;プロジェクトに必要なライブラリをインストールする 
&lt;pre&gt;
pip install simplejson foo bar ...
&lt;/pre&gt;
 ※ Windows 環境では以下のライブラリはバイナリインストール ?&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://mysql-python.sourceforge.net/" target="_blank" title="MySQL-Python"&gt;mysql-python&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://cx-oracle.sourceforge.net/" target="_blank" title="cx_Oracle"&gt;cx_Oracle&lt;/a&gt; (&lt;a href="http://sourceforge.net/projects/cx-oracle/files/4.4.1/" target="_blank" title="cx_Oracle 4.4.1 - 9i"&gt;4.4.1-9i&lt;/a&gt;, &lt;a href="http://sourceforge.net/projects/cx-oracle/files/5.1/" target="_blank" title="cx_Oracle-10g"&gt;5.1-10g&lt;/a&gt;, &lt;a href="http://sourceforge.net/projects/cx-oracle/files/5.1/" target="_blank" title="cx_Oracle 5.1-11g"&gt;5.1-11g&lt;/a&gt;)&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;virtualenvwrapper の利用方法&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;新規作成 &lt;br/&gt;&lt;code&gt;mkvirtualenv &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/li&gt; &lt;li&gt;削除 &lt;br/&gt;&lt;code&gt;rmvirtualenv &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/li&gt; &lt;li&gt;利用 &lt;br/&gt;&lt;code&gt;workon &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/li&gt; &lt;li&gt;一覧 &lt;br/&gt;&lt;code&gt;lsvirtualenv&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-6288454241797630679?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/f_EABxrcl1tXtRwbYjv27m6Czso/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/f_EABxrcl1tXtRwbYjv27m6Czso/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/f_EABxrcl1tXtRwbYjv27m6Czso/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/f_EABxrcl1tXtRwbYjv27m6Czso/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=pQ4ZJWPNB_w:wRLk_LCw0p0:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=pQ4ZJWPNB_w:wRLk_LCw0p0:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/pQ4ZJWPNB_w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/6288454241797630679/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/05/python-26.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/6288454241797630679?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/6288454241797630679?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/pQ4ZJWPNB_w/python-26.html" title="Python 環境構築メモ (2.6 系)" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/05/python-26.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IMQHo4cCp7ImA9WhZXFkg.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-7121563730241708200</id><published>2011-05-06T12:12:00.000+09:00</published><updated>2011-05-06T12:13:01.438+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-06T12:13:01.438+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="subversion" /><title>SVN リポジトリ間で特定ディレクトリの移動</title><content type="html">&lt;p&gt;いつも忘れるのでメモ&lt;/p&gt; &lt;p&gt;svnadmin と &lt;strong&gt;svndumpfilter&lt;/strong&gt; を利用する。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;svndumpfilter で dump から特定ディレクトリを抽出 
&lt;pre class="prettyprint"&gt;
svnadmin dump /path/to/svn/repo | svndumpfilter include /path/to/project/trunk &amp;gt; project.dump
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;svnadmin で移行先のリポジトリにロード 
&lt;pre class="prettyprint"&gt;
cat project.dump | sudo svnadmin load /path/to/svn/old
&lt;/pre&gt;
&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;移動元リポジトリの階層は維持される。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-7121563730241708200?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/H3NRQy_KSDzutXB1mwqBkKclkvs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H3NRQy_KSDzutXB1mwqBkKclkvs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/H3NRQy_KSDzutXB1mwqBkKclkvs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H3NRQy_KSDzutXB1mwqBkKclkvs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=t99eZXOSUus:Qr4Y9xfurpY:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=t99eZXOSUus:Qr4Y9xfurpY:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/t99eZXOSUus" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/7121563730241708200/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/05/svn.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7121563730241708200?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7121563730241708200?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/t99eZXOSUus/svn.html" title="SVN リポジトリ間で特定ディレクトリの移動" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2011/05/svn.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYBQ345fCp7ImA9WhZVEU8.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-7215377034345140244</id><published>2011-03-05T18:19:00.001+09:00</published><updated>2011-05-23T14:05:52.024+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-23T14:05:52.024+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>10 分で学ぶ Python のチュートリアル</title><content type="html">&lt;p&gt;"&lt;a href="http://www.korokithakis.net/" target="_blank" title="Stavros' Stuff"&gt;Stavros' Stuff&lt;/a&gt;" というサイトに掲載されていた "&lt;a href="http://www.korokithakis.net/tutorials/python" target="_blank" title="Tutorial - Learn Python in 10 minutes"&gt;Tutorial - Learn Python in 10 minutes&lt;/a&gt;" という記事の&lt;del&gt;妙訳&lt;/del&gt; &lt;ins&gt;翻訳&lt;/ins&gt;です。これから Python をはじめたいという方向けです。ちょっと分かりやすいように ? 補足情報も付加しちゃってます。ついでに私が Python を書くときに意識していることも付加しちゃってます。付加情報が間違ってたらごめんなさい &amp;gt;&amp;lt;&lt;/p&gt; &lt;h3&gt;プロパティ&lt;/h3&gt; &lt;p&gt;Python は&lt;strong&gt;強い型付け&lt;/strong&gt; (strongly typed language)、&lt;strong&gt;動的型付け&lt;/strong&gt; (dynamically typed)、&lt;strong&gt;暗黙的型付け&lt;/strong&gt; (implicitly typed)、&lt;strong&gt;大文字小文字を区別&lt;/strong&gt; (case sensitive)、&lt;strong&gt;オブジェクト指向&lt;/strong&gt; (object-oriented) です。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;強い型付け言語の特徴: 処理や演算が間違った型の引数を受けとることが出来ない (C 言語とかは弱い型付け)。安全ですね。&lt;/li&gt; &lt;li&gt;動的型付け言語の特徴: 型の検査を実行時に行うことが多い。簡単に言うと、型は変数ではなく値に付けられます。&lt;/li&gt; &lt;li&gt;暗黙型付け言語の特徴: 明示的に指定しなくてもコンパイラが自動的に型変換を判断してくれる&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;ヘルプ&lt;/h3&gt; &lt;p&gt;Python のヘルプは常にインタプリタから利用する事ができます。もし、オブジェクトの動作について調べたい場合は、&lt;code class="prettyprint"&gt;help(&amp;lt;object&amp;gt;)&lt;/code&gt; を呼び出しましょう。また、&lt;code class="prettyprint"&gt;dir(&amp;lt;object&amp;gt;)&lt;/code&gt; でオブジェクトのメソッドや変数等のメンバ一覧を参照したり、&lt;code class="prettyprint"&gt;&amp;lt;object&amp;gt;.__doc__&lt;/code&gt; でドキュメントを参照するのも便利ですよ。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;gt;&amp;gt;&amp;gt; help(5)
Help on int object:
class int(object)
...

&amp;gt;&amp;gt;&amp;gt; dir(5)
['__abs__', '__add__', ...]

&amp;gt;&amp;gt;&amp;gt; print abs.__doc__
abs(number) -&amp;gt; number

Return the absolute value of the argument.
&lt;/pre&gt;
 &lt;p&gt;蛇足ですが、個人的には &lt;a href="http://ipython.scipy.org/" target="_blank" title="IPython"&gt;IPython&lt;/a&gt; 使ってます。&lt;code class="prettyprint"&gt;&amp;lt;object&amp;gt;?&lt;/code&gt; &lt;code class="prettyprint"&gt;&amp;lt;object&amp;gt;??&lt;/code&gt; でドキュメントを含む様々な情報を参照できちゃいます。&lt;/p&gt; &lt;h3&gt;構文 (シンタックス)&lt;/h3&gt; &lt;p&gt;Python は&lt;strong&gt;ステートメントの終端文字がなく&lt;/strong&gt;、&lt;strong&gt;ブロックをインデントで指定&lt;/strong&gt;します。ブロックの始まりにインデントし、終わりにインデントを戻します。コロン (&lt;code class="prettyprint"&gt;:&lt;/code&gt;) で終了するステートメント以下をインデントします。&lt;strong&gt;コメント&lt;/strong&gt;は、1 行ならシャープ &lt;code class="prettyprint"&gt;#&lt;/code&gt; の後に続け、複数行にわたる場合は&lt;strong&gt;複数行の文字列&lt;/strong&gt; &lt;code class="prettyprint"&gt;"""スパム\nエッグ"""&lt;/code&gt; にします。&lt;strong&gt;値の割り当て&lt;/strong&gt; (厳密にはオブジェクトへの名前付け) は等記号 "&lt;code class="prettyprint"&gt;=&lt;/code&gt;" を使い、等価比較は 2 つの等記号 "&lt;code class="prettyprint"&gt;==&lt;/code&gt;" を使います。"&lt;code class="prettyprint"&gt;+=&lt;/code&gt;" や "&lt;code class="prettyprint"&gt;-=&lt;/code&gt;" 演算子で、演算子の右に記載した値でインクリメントやデクリメントすることができます。これは文字列を含む多くの型で利用できます。また、複数の変数を 1 行で定義することができます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;gt;&amp;gt;&amp;gt; spam = 3
&amp;gt;&amp;gt;&amp;gt; spam
3
&amp;gt;&amp;gt;&amp;gt; spam += 2
&amp;gt;&amp;gt;&amp;gt; spam
5
&amp;gt;&amp;gt;&amp;gt; spam -= 1
&amp;gt;&amp;gt;&amp;gt; spam
4
# 一行のコメント
"""This is a multiline comment.
The following lines concatenate the two strings."""
u"""これは複数行コメントです。
日本語でのコメントはユニコードでコメントする事をお勧めします。
あとで __doc__ とかで文字化けせずに表示したいでしょ :D
下の行では、2 つの文字列を連結しています。"""
&amp;gt;&amp;gt;&amp;gt; egg = "Hello"
&amp;gt;&amp;gt;&amp;gt; egg += " world!"
&amp;gt;&amp;gt;&amp;gt; print egg
Hello world!
# ユニコード文字列だって
&amp;gt;&amp;gt;&amp;gt; ja = u"こんにちわ"
&amp;gt;&amp;gt;&amp;gt; ja += u"世界！"
&amp;gt;&amp;gt;&amp;gt; print ja
こんにちわ世界！
# 1 行で変数の交換だってできちゃいます。
# 値が割り当てられているわけではないので、強い型付けによる制限を受けません。
# 新しいオブジェクトが名前に紐付けられます。
&amp;gt;&amp;gt;&amp;gt; spam, egg = egg, spam
&amp;gt;&amp;gt;&amp;gt; print spam
Hello world!
&amp;gt;&amp;gt;&amp;gt; egg
4
&lt;/pre&gt;
 &lt;h3&gt;データ型&lt;/h3&gt; &lt;p&gt;Python で利用できるデータ構造は&lt;strong&gt;リスト&lt;/strong&gt; (list)、&lt;strong&gt;タプル&lt;/strong&gt; (tuple)、&lt;strong&gt;辞書&lt;/strong&gt; (dict)、&lt;strong&gt;セット&lt;/strong&gt; (set) (Python 2.5 以前は sets モジュールとして提供) です。リストは一次元配列 (もちろんリスト内にリストを含めることができます)、辞書は連想配列 (もしくはハッシュテーブル)、タプルはイミュータブル (状態を変更することができない) 一次元配列です。Python の配列は型による制限がないため、数値や文字列などをリスト/タプル/辞書/セット内に混在させることができます。すべての配列型で要素のインデックスは 0 から始まります。インデックスに負の数のを指定すると配列の終わりから数えるため、最後の要素のインデックスは -1 となります。関数を変数とすることができます。&lt;strong&gt;Python はファーストクラスオブジェクト&lt;/strong&gt;です。これは&lt;a href="http://shibu.jp/" target="_blank" title="渋川よしきのウェブサイト。ソフトウェア開発とか、ライフハックとか"&gt;渋川先生&lt;/a&gt;が翻訳されている "&lt;a href="http://python-history-jp.blogspot.com/2009/04/blog-post_1081.html" target="_blank" title="すべてをファーストクラスに"&gt;The history of Python&lt;/a&gt;" のブログを見ると幸せになれます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;gt;&amp;gt;&amp;gt; sample = [1, [u"日本語", "list"], ("a", "tuple")]
&amp;gt;&amp;gt;&amp;gt; mylist = ["List item 1", 2, 3.14]
&amp;gt;&amp;gt;&amp;gt; mylist[0] = "List item 1 again"
&amp;gt;&amp;gt;&amp;gt; mylist[-1] = 3.14
&amp;gt;&amp;gt;&amp;gt; mydict = {"Key 1": "Value 1", 2: 3, "pi": 3.14}
&amp;gt;&amp;gt;&amp;gt; mydict["pi"] = 3.15
&amp;gt;&amp;gt;&amp;gt; mytuple = (1, 2, 3)
&amp;gt;&amp;gt;&amp;gt; myfunction = len
&amp;gt;&amp;gt;&amp;gt; print myfunction(mylist)
3
&lt;/pre&gt;
 &lt;p&gt;コロン (:) を使って配列内の&lt;strong&gt;指定した範囲&lt;/strong&gt;にアクセスすることができます。インデックスの開始を省略すると最初の要素から、インデックスの終了を省略すると最後の要素までとなります。負のインデックスを指定すると、最後のアイテム (-1 が最後のアイテムのインデックス) から数えます。&lt;/p&gt; &lt;p&gt;どこでどういうデータ型を使うかというのは非常に重要です。各データ型の特徴をしっかり把握しておくと幸せになれます。配列内でユニークにデータを持たせたい場合はセット、順番を保証したいのであればリスト！などなど&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;gt;&amp;gt;&amp;gt;  mylist = ["List item 1", 2, 3.14]
&amp;gt;&amp;gt;&amp;gt;  print mylist[:]
['List item 1', 2, 3.1400000000000001]
&amp;gt;&amp;gt;&amp;gt;  print mylist[0:2]
['List item 1', 2]
&amp;gt;&amp;gt;&amp;gt;  print mylist[-3:-1]
['List item 1', 2]
&amp;gt;&amp;gt;&amp;gt;  print mylist[1:]
[2, 3.14]
&lt;/pre&gt;
 &lt;p&gt;ちなみに &lt;code class="prettyprint"&gt;array[:]&lt;/code&gt; で配列の &lt;ins&gt;シャローコピー&lt;/ins&gt; &lt;del&gt;ディープコピー&lt;/del&gt; ができます。元の配列を保持したまま、配列を操作する時に使います。&lt;/p&gt; &lt;h3&gt;文字列&lt;/h3&gt; &lt;p&gt;文字列はシングルクォーテーションかダブルクォーテーションの何れかで定義でき、&lt;code class="prettyprint"&gt;"He said 'Hello'"&lt;/code&gt; のようにクォーテーション内で異なるクォーテーションを使用することができます。複数行にまたがる文字列は 3 つのダブルクォーテーション (もしくはシングルクォーテーション) で囲みます。Python は&lt;strong&gt;ユニコードをサポート&lt;/strong&gt;しており、&lt;code class="prettyprint"&gt;u"これはユニコード文字"&lt;/code&gt; と定義できます。&lt;strong&gt;文字列フォーマット操作&lt;/strong&gt;は % (モジュロ) 演算子とタプルを使います。各 %s や %d 等が、左から右へタプル内の各アイテムに置き換えられます。タプルの変わりに辞書を使うことも出来ます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
&amp;gt;&amp;gt;&amp;gt; print u"名前: %s\n数字: %d\n少数: %f\n文字列: %s" % (myclass.name, 3, 3.14, 3 * "-")
名前: Poromenos
数字: 3
少数: 3.140000
文字列: ---

multiline = """This is
a multiline
string."""

# WARNING: Watch out for the trailing s in "%(key)s".
&amp;gt;&amp;gt;&amp;gt; print "This %(verb)s a %(noun)s." % {"noun": "test", "verb": "is"}
This is a test.
&lt;/pre&gt;
 &lt;p&gt;美しいコードを書くために、複数行にまたがる文字列の 3 つの引用符はダブルクォーテーションを、ログやメッセージなどユーザに表示や通知する文字列もダブルクォーテーションを、その他コード内で利用する設定情報 (URL や DB接続情報等) や定数はシングルクォーテーションを使いましょう。っていうかそう決めておくと、後でコードが追いやすいです。運用する人がログやメッセージを追加、変更したいのであればダブルクォートを追いかける、ロジックや環境が変更した場合はシングルクォートを追いかける、とかできます。また、美しくコードを書くために複数行文字列は非明示的文字列連結を使うというテクニックもありますよ。&lt;/p&gt; &lt;h3&gt;フロー制御構文&lt;/h3&gt; &lt;p&gt;フロー制御構文は &lt;code class="prettyprint"&gt;if&lt;/code&gt;、&lt;code class="prettyprint"&gt;for&lt;/code&gt;、&lt;code class="prettyprint"&gt;while&lt;/code&gt; です。&lt;code class="prettyprint"&gt;switch&lt;/code&gt; や &lt;code class="prettyprint"&gt;select&lt;/code&gt; はありませんが、&lt;code class="prettyprint"&gt;if&lt;/code&gt; や &lt;code class="prettyprint"&gt;elif&lt;/code&gt; で代用します。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
rangelist = range(10)
&amp;gt;&amp;gt;&amp;gt; print rangelist
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

for number in range(10):
    # number がタプル内に含まれているかをチェック
    if number in (3, 4, 7, 9):
        # "break" は "else" に行かずに for を終了します
        break
    else:
        # "continue" は次のループを続けます
        continue
else:
    # "else" は "break" 以外の場合に実行されます
    pass # 何もしない場合は "pass"　と記載

if rangelist[1] == 2:
    print "The second item (lists are 0-based) is 2"
elif rangelist[1] == 3:
    print "The second item (lists are 0-based) is 3"
else:
    print "Dunno"

while rangelist[1] == 1:
    pass
&lt;/pre&gt;
 &lt;h3&gt;関数&lt;/h3&gt; &lt;p&gt;関数は &lt;strong&gt;"def" で宣言&lt;/strong&gt;します。必須の引数の後に、デフォルトの値を指定した&lt;strong&gt;オプション引数&lt;/strong&gt;を宣言することができます。&lt;strong&gt;名前付け引数&lt;/strong&gt;は値を渡す引数の名前を指定する事が出来ます。関数が返したい&lt;strong&gt;結果が複数&lt;/strong&gt;ある場合、タプルを返すと、効率的に &lt;strong&gt;複数の結果&lt;/strong&gt;をアンパックすることができます。&lt;strong&gt;ラムダ関数&lt;/strong&gt;は 1 行の構文を含むアドホック関数を定義します。パラメータは参照渡しですが、イミュータブル型 (タプル、数値、文字列等) は変更できません。これは&lt;strong&gt;引数としてそのオブジェクトのメモリ上の位置を渡している&lt;/strong&gt;ためであり、それを&lt;strong&gt;他のオブジェクトへ結びつけると今までのオブジェクトは破棄され&lt;/strong&gt;、イミュータブル型のオブジェクトは新しく結びつけられたオブジェクトになってしまいます。イミュータブル型のオブジェクトのうち配列に関しては、上述したシャローコピー (array[:]) で渡してあげると、新たなオブジェクトを作成するので、元の配列 (シャローコピーなので値は参照です) を保持することができます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# def f(x): return x + 1 と同じこと
functionvar = lambda x: x + 1
&amp;gt;&amp;gt;&amp;gt; print functionvar(1)
2

# an_int と a_string は初期値を持つオプション引数です
# 最初の引数は省略することができません
def passing_example(a_list, an_int=2, a_string="A default string"):
    a_list.append("A new item")
    an_int = 4
    return a_list, an_int, a_string

&amp;gt;&amp;gt;&amp;gt; my_list = [1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; my_int = 10
&amp;gt;&amp;gt;&amp;gt; print passing_example(my_list, my_int)
([1, 2, 3, 'A new item'], 4, "A default string")
&amp;gt;&amp;gt;&amp;gt; my_list
[1, 2, 3, 'A new item']
&amp;gt;&amp;gt;&amp;gt; my_int
10
&lt;/pre&gt;
 &lt;p&gt;ちなみにオプション引数と、名前付け引数を混同している？と見受けられる文献をたまに見かけますが、両者はまったく違います。オプション引数は前述の通り、デフォルト値が指定されたオプショナルの引数。名前付け引数というのは、引数の名前を指定して値を渡すことができる機能のことです。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
def spam(foo, bar="optional"):
    # foo は必須の引数 
    # bar はオプション引数
    print foo, bar

# オプション引数を指定しない、非名前付け引数呼び出し
spam("mandatory")
# オプション引数を指定した、非名前付け引数呼び出し
spam("mandatory", "optional")
# オプション引数を指定した、名前付け引数呼び出し 1
spam(foo="mandatory", bar="optional")
# オプション引数を指定した、名前付け引数呼び出し 2
# 名前付け引数を使っても、引数の順番は守ろうね！読みにくくなる。
spam(bar="optional", foo="mandatory")

# すべて "mandatory optional" と出力されます
&lt;/pre&gt;
 &lt;h3&gt;クラス&lt;/h3&gt; &lt;p&gt;Python のクラスは、制限付き多重継承をサポートしています。プライベート (厳密にはプライベートではない) 変数やメソッドは、 __spam のように最初に 2 つ以上のアンダーラインがある名前で宣言します。クラスのインスタンスには任意の名前を付けることができます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
class MyClass:
    common = 10
    def __init__(self):
        self.myvariable = 3
    def myfunction(self, arg1, arg2):
        return self.myvariable

&amp;gt;&amp;gt;&amp;gt; classinstance = MyClass()
&amp;gt;&amp;gt;&amp;gt; classinstance.myfunction(1, 2)
3
# 変数 "common" はすべてのクラスに共通するクラス変数
&amp;gt;&amp;gt;&amp;gt; classinstance2 = MyClass()
&amp;gt;&amp;gt;&amp;gt; classinstance.common
10
&amp;gt;&amp;gt;&amp;gt; classinstance2.common
10
# クラス変数の更新は、インスタンスではなくクラス名による操作
&amp;gt;&amp;gt;&amp;gt; MyClass.common = 30
&amp;gt;&amp;gt;&amp;gt; classinstance.common
30
&amp;gt;&amp;gt;&amp;gt; classinstance2.common
30
# クラス変数を更新せずにインスタンス変数のみを更新
&amp;gt;&amp;gt;&amp;gt; classinstance.common = 10
# クラス変数からインスタンス変数へ
&amp;gt;&amp;gt;&amp;gt; classinstance.common
10
&amp;gt;&amp;gt;&amp;gt; classinstance2.common
30
&amp;gt;&amp;gt;&amp;gt; MyClass.common = 50
# "common" はインスタンス変数になっているため変更されない
&amp;gt;&amp;gt;&amp;gt; classinstance.common
10
# "common" はクラス変数のままなので変更される
&amp;gt;&amp;gt;&amp;gt; classinstance2.common
50

# MyClass を継承したクラス
# クラスを多重継承したい場合は以下のように定義する:
# class OtherClass(MyClass1, MyClass2, MyClassN)
class OtherClass(MyClass):
    # 変数 "self" はクラスインスタンスへの参照が自動的に代入される
    def __init__(self, arg1):
        self.myvariable = 3
        print arg1

&amp;gt;&amp;gt;&amp;gt; classinstance = OtherClass("hello")
hello
&amp;gt;&amp;gt;&amp;gt; classinstance.myfunction(1, 2)
3
# このクラスには "test" というメンバ変数を持っていませんが、
# そのインスタンスに対していつでも追加することができます。
&amp;gt;&amp;gt;&amp;gt; classinstance.test = 10
&amp;gt;&amp;gt;&amp;gt; classinstance.test
10
&lt;/pre&gt;
 &lt;h3&gt;例外&lt;/h3&gt; &lt;p&gt;Python の例外は &lt;strong&gt;try-except ブロック&lt;/strong&gt;でハンドリングします。また finally 句で、事後処理をする事ができます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
def spam():
    try:
        # 0 による乗算で例外をスロー
        10 / 0
    except ZeroDivisionError:
        # 例外発生時の処理
        print "Oops, invalid."
    else:
        # 例外が発生しなかった場合の処理
        pass
    finally:
        # 例外発生の有無にかかわらず処理
        print "We're done with that."

&amp;gt;&amp;gt;&amp;gt; spam()
Oops, invalid.
We're done with that.
&lt;/pre&gt;
 &lt;h3&gt;インポート&lt;/h3&gt; &lt;p&gt;外部のライブラリは &lt;code class="prettyprint"&gt;import &amp;lt;libname&amp;gt;&lt;/code&gt; でインポートします。また、from &amp;lt;libname&amp;gt; import &amp;lt;funcname&amp;gt; を使って、ライブラリ内の関数をインポートすることもできます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
import random
from time import clock

randomint = random.randint(1, 100)
&amp;gt;&amp;gt;&amp;gt; print randomint
64
&lt;/pre&gt;
 &lt;p&gt;美しいコードを書くために &lt;code class="prettyprint"&gt;from &amp;lt;libname&amp;gt; import *&lt;/code&gt; を多用するのは避けましょう。名前空間が心配になります。あと、なるべく関数ではなくモジュールレベルでインポートしましょう。&lt;code class="prettyprint"&gt;read&lt;/code&gt; とかいう関数とかかぶりそうですよね。それに &lt;code class="prettyprint"&gt;spam.read&lt;/code&gt; や &lt;code class="prettyprint"&gt;egg.read&lt;/code&gt; と書いてあったほうが脳に優しいです。&lt;/p&gt; &lt;h3&gt;ファイル入出力&lt;/h3&gt; &lt;p&gt;Python には多くの標準ライブラリーが備わっています。例えば、ファイル入出力を使ったシリアライズ (pickle を使ってデータ構造を文字列に変換する) は以下のように書くことができます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
import pickle
mylist = ["This", "is", 4, 13327]
# "C:\binary.dat" を書込権限で開く
# ファイル名の前の "r" は文字列をエスケープしないっていう意味
# "raw string" の "r"
myfile = file(r"C:\binary.dat", "w")
pickle.dump(mylist, myfile)
myfile.close()

myfile = file(r"C:\text.txt", "w")
myfile.write("This is a sample string")
myfile.close()

myfile = file(r"C:\text.txt")
&amp;gt;&amp;gt;&amp;gt; print myfile.read()
'This is a sample string'
myfile.close()

# ファイルを読取権限で開く
myfile = file(r"C:\binary.dat")
loadedlist = pickle.load(myfile)
myfile.close()
&amp;gt;&amp;gt;&amp;gt; print loadedlist
['This', 'is', 4, 13327]
&lt;/pre&gt;
 &lt;h3&gt;その他&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;同時に複数のコンディションをチェック&lt;/strong&gt;できます。1 &amp;lt; n &amp;lt; 3 では n が 1 より大きく、 3 より小さいかどうかをチェックします。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;配列からアイテムを削除&lt;/strong&gt;したい場合は del を使います。&lt;/li&gt; &lt;li&gt;リスト内包表記はリストを生成するための強力な方法を提供します。それは複数の for-in と、if で条件を含める事ができます。 
&lt;pre class="prettyprint"&gt;
&amp;gt;&amp;gt;&amp;gt; spam = [1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; egg = [3, 4, 5]
&amp;gt;&amp;gt;&amp;gt; print [x * y for x in spam for y in egg]
[3, 4, 5, 6, 8, 10, 9, 12, 15]
&amp;gt;&amp;gt;&amp;gt; print [x for x in spam if 4 &amp;gt; x &amp;gt; 1]
[2, 3]
# "any" でアイテム内に値が真値であるかチェックできます
&amp;gt;&amp;gt;&amp;gt; any([i % 3 for i in [3, 3, 4, 4, 3]])
True
# 4 % 3 が 1 になり、1 は真値であるため、True を返します

# 条件に該当する値の個数を調べたい場合は以下のように書けます
&amp;gt;&amp;gt;&amp;gt; sum(1 for i in [3, 3, 4, 4, 3] if i == 4)
2

# 値の削除
&amp;gt;&amp;gt;&amp;gt; del spam[0]
&amp;gt;&amp;gt;&amp;gt; print spam
[2, 3]
&amp;gt;&amp;gt;&amp;gt; del spam
&lt;/pre&gt;
&lt;/li&gt; &lt;li&gt;&lt;strong&gt;グローバル変数&lt;/strong&gt;は関数外に宣言し、特別な宣言をしなくても関数内で参照できます。しかし値を変更したい場合は、関数の最初に "global" の後に変更する変数を記述する必要があります。"global" 宣言しない場合、Python はそれを新しい新しいローカル変数とみなします。 
&lt;pre class="prettyprint"&gt;
number = 5

def spam():
    # 5 と出力します
    print number

def egg():
    # 新しい変数を作る前にその変数を参照しているとみなされ、
    # 例外がスローされます。
    print number
    number = 3

def yetanother():
    global number
    # グローバル変数を書き換える
    number = 3
&lt;/pre&gt;
&lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-7215377034345140244?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5muTRjb2ukduSZrgh1XgM2YwBlw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5muTRjb2ukduSZrgh1XgM2YwBlw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5muTRjb2ukduSZrgh1XgM2YwBlw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5muTRjb2ukduSZrgh1XgM2YwBlw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=ea7eZmjp4s4:VAd0ykgitmk:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=ea7eZmjp4s4:VAd0ykgitmk:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/ea7eZmjp4s4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/7215377034345140244/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2011/03/10-python.html#comment-form" title="4 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7215377034345140244?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7215377034345140244?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/ea7eZmjp4s4/10-python.html" title="10 分で学ぶ Python のチュートリアル" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://surgo.jp/2011/03/10-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUCRX4-cCp7ImA9Wx9QEkk.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-270899971666058834</id><published>2010-12-24T21:19:00.001+09:00</published><updated>2010-12-25T10:57:44.058+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-25T10:57:44.058+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vim" /><title>From QuickBuf to DumbBuf</title><content type="html">&lt;p&gt;こんにちは。サーバの標準エディタを emacs にしたあげく vi を emacs のシンボリックリンクにした方とは、それ依頼お話していない vimmer です (嘘。今もっすご興奮しています。1 年ぶりに vimfiles の中身が更新されましたよ！&lt;/p&gt; &lt;p&gt;複数ファイルを同時に編集するときはバッファーを一覧表示したり、簡単に切り替えたりするバッファーマネージャ系プラグインがかかせませぬ。今までは &lt;a href="http://www.vim.org/scripts/script.php?script_id=1910" target="_blank" title="QuickBuf : Very small, clean but quick and powerful buffer manager!"&gt;QuickBuf&lt;/a&gt; というプラグインを使っていました。ただ、QuickBuf は表示できる行数を計算し、その行数を超えるファイル数を開くと "No room to display buffer list..." っていうエラーが発生する難点がありました。脳内メモリが少なすぎてファイル名が覚えられないし、バッファー内から補完もしたい。&lt;code&gt;args *.py&lt;/code&gt; で 50 ファイルぐらい軽く開いちゃう人なのでそれは困る・・・。そこで出会ったのが &lt;a href="http://www.vim.org/scripts/script.php?script_id=2783" target="_blank" title="DumbBuf : simple buffer manager like QuickBuf.vim"&gt;DumbBuf&lt;/a&gt; です！これすごいですよ！！インストール後、QuickBuf 同様、_vimrc に &lt;code&gt;dumbbuf_hotkey&lt;/code&gt; を指定します。例) &lt;code&gt;let g:dumbbuf_hotkey=';;'&lt;/code&gt; これで快適なバッファーマネジメントができるようになりました。&lt;/p&gt; &lt;p&gt;ホットキーに割り当てたキーマップをタイプすると、バッファーが一覧表示されます。&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;a href="http://lh4.ggpht.com/_prnhyeZ3SnQ/TRSPu4twj5I/AAAAAAAAHF8/jZ6hbTlEmvM/dumpbuf01.PNG"&gt;&lt;img src="http://lh6.ggpht.com/_prnhyeZ3SnQ/TRSPvXEomuI/AAAAAAAAHGA/rnqZ8PZBO28/zrtn_003p3884b9e1_tn.jpg?imgmax=400" style="WIDTH: 400px; HEIGHT: 324px" height="324" width="400"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;ここまでは Quick Buf と一緒です。QuickBuf と異なるところは、バッファ内のファイル数が 10 行を超えると、自動的にローテートしてくれます。もちろん j, k で選択行を上下、&amp;lt;c-f&amp;gt;, &amp;lt;c-b&amp;gt; でページ送り/戻しができます。ページ送りだけで、ファイル選択が断然楽になりましたね！&lt;/p&gt; &lt;p&gt;あと、普通に &lt;code&gt;/&lt;/code&gt; でファイル名検索もできますよ！&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;a href="http://lh5.ggpht.com/_prnhyeZ3SnQ/TRSPvoEapGI/AAAAAAAAHGE/gMjze-CaJYU/dumpbuf02.PNG"&gt;&lt;img src="http://lh6.ggpht.com/_prnhyeZ3SnQ/TRSPvw6S9KI/AAAAAAAAHGI/q4Z4RKCgVOU/zrtn_002n79de0ed4_tn.jpg?imgmax=400" style="WIDTH: 400px; HEIGHT: 324px" height="324" width="400"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;これさえあれば 100 ファイルぐらい開いても、お望みのファイルに一瞬でたどり着けますね！！！痒いところに手が届きすぎです＞＜ 作者の &lt;a href="http://d.hatena.ne.jp/tyru/" target="_blank" title="id:tyru"&gt;id:tyru&lt;/a&gt; さんありがとうございます！&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-270899971666058834?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fXEk8P0JQ3FYpq_c5i7YmXBQqAI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fXEk8P0JQ3FYpq_c5i7YmXBQqAI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fXEk8P0JQ3FYpq_c5i7YmXBQqAI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fXEk8P0JQ3FYpq_c5i7YmXBQqAI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=s4tqg9ykhJ8:2Kt8YfLETLA:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=s4tqg9ykhJ8:2Kt8YfLETLA:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/s4tqg9ykhJ8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/270899971666058834/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/12/from-quickbuf-to-dumbbuf.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/270899971666058834?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/270899971666058834?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/s4tqg9ykhJ8/from-quickbuf-to-dumbbuf.html" title="From QuickBuf to DumbBuf" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_prnhyeZ3SnQ/TRSPvXEomuI/AAAAAAAAHGA/rnqZ8PZBO28/s72-c/zrtn_003p3884b9e1_tn.jpg?imgmax=400" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/12/from-quickbuf-to-dumbbuf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAFQXg6eyp7ImA9Wx9QEEU.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-5687900002698508960</id><published>2010-12-23T15:11:00.001+09:00</published><updated>2010-12-23T15:11:50.613+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-23T15:11:50.613+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="server" /><category scheme="http://www.blogger.com/atom/ns#" term="pyside" /><category scheme="http://www.blogger.com/atom/ns#" term="WAF" /><category scheme="http://www.blogger.com/atom/ns#" term="wsgi" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><category scheme="http://www.blogger.com/atom/ns#" term="pyqt" /><title>WSGI on Qt (PyQt or PySide)</title><content type="html">&lt;p&gt;こんにちは、Python 会の。。。思いつきませんでした。初 "&lt;a href="http://atnd.org/events/10465" target="_blank" title="Python Web フレームワーク アドベントカレンダー2010"&gt;Python Web フレームワーク アドベントカレンダー2010&lt;/a&gt;" に参加させていただくことになりました。よろしくおねがいします。アドベントカレンダー参加者のブログは &lt;a href="http://cielquis.net/advent-calendar/python-jp-2010.html" target="_blank" title="Python Advent Calendar jp 2010"&gt;cielquis.net&lt;/a&gt; に綺麗にまとめられていますよ。&lt;/p&gt; &lt;p&gt;ごめんなさい。Web アプリケーションフレームワークの作成なんて 1 日じゃむりぽ＞＜。メインで使ってるフレームワークは、&lt;a href="http://www.djangoproject.com/" target="_blank" title="Django"&gt;Django&lt;/a&gt; か &lt;a href="http://code.google.com/appengine/docs/python/tools/webapp/" target="_blank" title="The webapp Framework"&gt;webapp&lt;/a&gt; ぐらい。。。最近 dis られてるので、Django 記事書くのもあれだ・・・。&lt;/p&gt; &lt;p&gt;ということで本題です。Python は WSGI (Web Server Gateway Interface) という Web アプリケーションと Web サーバ間の共通インターフェースがあります。そのインターフェースを実装したオブジェクトは、Web アプリケーションとして動作させることができます。ということで、デスクトップアプリケーションを Web アプリケーションにする方法を書きたいと思います。今回は Qt の Python binding な &lt;a href="http://www.riverbankcomputing.co.uk/software/pyqt/intro" target="_blank" title="PyQt"&gt;PyQt&lt;/a&gt; / &lt;a href="http://www.pyside.org/" target="_blank" title="PySide"&gt;PySide&lt;/a&gt; で WSGI アプリケーションを作ってみたいと思います。実装は PySide ですが、 PyQt でも動くはずです。&lt;/p&gt; &lt;h4&gt;STEP1: PySide で Hello World!&lt;/h4&gt; &lt;p&gt;ほんと Web アプリケーションじゃなくて申し訳ないですが、最初に PySide で "Hello World!" を表示します。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
import sys

from PySide import QtCore, QtNetwork, QtGui

class QWSGILabel(QtGui.QLabel):
    def __init__(self, text, parent=None):
        super(QWSGILabel, self).__init__(text, parent=parent)

class QHttpWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(QHttpWidget, self).__init__(parent=parent)
        self.setLayout(QtGui.QVBoxLayout(self))

        # Create label instance
        qwsgilabel = QWSGILabel("Hello World!", parent=self)
        self.layout().addWidget(qwsgilabel)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = QHttpWidget()
    window.show()
    sys.exit(app.exec_())
&lt;/pre&gt;
 &lt;p&gt;QLabel を単純に継承した QWSGILabel に "Hello World!" と表示しています。実行すると、以下のようなウィンドウが表示されます。&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;img src="http://lh6.ggpht.com/_prnhyeZ3SnQ/TRLoH1hcYYI/AAAAAAAAHFk/wQhKExWMnNM/step1.png?imgmax=144" alt="step1.png" height="68" width="123"/&gt;&lt;/p&gt; &lt;h4&gt;STEP2: WSGI on PySide で Hello World!&lt;/h4&gt; &lt;p&gt;STEP1 で作成した QWSGILabel を、さっそく Web アプリケーションにしてみます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
import sys

from wsgiref.util import setup_testing_defaults
from wsgiref import simple_server

from PySide import QtCore, QtNetwork, QtGui

ENCODING = 'utf-8'

class QWSGILabel(QtGui.QLabel):
    def __init__(self, text, parent=None):
        super(QWSGILabel, self).__init__(text, parent=parent)

    def __call__(self, environ, start_response):
        """WSGI Web application interface"""

        setup_testing_defaults(environ)
        start_response('200 OK', [('Content-type', 'text/html'), ])
        return self.text().encode(ENCODING) # Return label text

class QHttpThread(QtCore.QThread):
    u"""Http threads"""

    def __init__(self, wsgi_server, parent=None):
        super(QHttpThread, self).__init__(parent=parent)
        self.wsgi_server = wsgi_server
        self.__is_run = False

    def run(self):
        self.__is_run = True
        while (self.__is_run):
            self.wsgi_server.handle_request()

    def stop(self):
        self.__is_run = False

class QHttpWidget(QtGui.QWidget):
    def __init__(self, host='localhost', port=8000, parent=None):
        super(QHttpWidget, self).__init__(parent=parent)
        self.setLayout(QtGui.QVBoxLayout(self))

        # Create label instance
        qwsgilabel = QWSGILabel("Hello World!", parent=self)
        self.layout().addWidget(qwsgilabel)

        # Create and start WSGI Web server
        wsgi_server = QHttpThread(
                simple_server.make_server(host, port, qwsgilabel), parent=self)
        wsgi_server.start()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = QHttpWidget()
    window.show()
    sys.exit(app.exec_())
&lt;/pre&gt;
 &lt;p&gt;QWSGILabel に &lt;code&gt;__call__&lt;/code&gt; 関数を追加し、ラベルにセットされているテキストを返すシンプルな Web アプリケーションを作成しています。そして、QThread を継承した QHttpThread に Web サーバを登録し、スレッドを開始しています。実行すると、STEP1 と同じウィンドウが起動します。起動中にブラウザからアクセスすると、"Hello World!" が表示されます。&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;img src="http://lh4.ggpht.com/_prnhyeZ3SnQ/TRLoILnFqkI/AAAAAAAAHFo/HE4jf5J23qI/step2.png?imgmax=288" alt="step2.png" height="151" width="265"/&gt;&lt;/p&gt; &lt;h4&gt;STEP 3: WSGI on PySide でフォーム操作&lt;/h4&gt; &lt;p&gt;簡単な GET リクエストが動いたので、簡単なフォーム操作をしてみたいと思います。せっかくなので、WSGI サーバの起動と停止もできるようにして見ました。ソースは長くなっちゃったので &lt;a href="https://bitbucket.org/Surgo/qtwsgi/src/6a69932b631c/step3.py" target="_blank" title="Surgo / qtwsgi"&gt;bitbucket&lt;/a&gt; にのっけました。Qwidget を継承した QWSGIFormWidget に &lt;code&gt;__call__&lt;/code&gt; を追加し、フォームを制御しています。QWSGIFormWidget に テキストインプット (QWSGILineEdit) やセレクトボックス (QWSGIQComboBox) を追加し、&lt;code&gt;REQUEST_METHOD&lt;/code&gt; が POST だった時にそれぞれを POST された値で更新 (&lt;code&gt;update(value)&lt;/code&gt;) するようになってます。&lt;code&gt;html()&lt;/code&gt; と &lt;code&gt;update(value)&lt;/code&gt; を追加した QWidget のサブクラスであれば、他のフォーム部品も動くはずです。起動すると以下のように、デスクトップアプリケーションとブラウザ間で通信することができます。&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;img src="http://lh3.ggpht.com/_prnhyeZ3SnQ/TRLoIe8vn5I/AAAAAAAAHFs/SNvWiiydxrE/step3_1.png?imgmax=288" alt="step3_1.png" height="175" width="208"/&gt;&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;"run" ボタンを押すと Web サーバが起動&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;img src="http://lh5.ggpht.com/_prnhyeZ3SnQ/TRLoI_xj5HI/AAAAAAAAHFw/Qt5p99Upkgc/step3_2.png?imgmax=288" alt="step3_2.png" height="265" width="265"/&gt;&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;ブラウザからアクセス&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;img src="http://lh4.ggpht.com/_prnhyeZ3SnQ/TRLoJOMJyaI/AAAAAAAAHF0/KriegPPMgQ4/step3_3.png?imgmax=288" alt="step3_3.png" height="265" width="265"/&gt;&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;値を変えて "submit"&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;&lt;img src="http://lh4.ggpht.com/_prnhyeZ3SnQ/TRLoJA7FZjI/AAAAAAAAHF4/qXZbVCoXGyo/step3_4.png?imgmax=288" alt="step3_4.png" height="175" width="208"/&gt;&lt;/p&gt; &lt;p style="TEXT-ALIGN: center"&gt;一瞬で各値が更新されます&lt;/p&gt; &lt;p&gt;もちょっと時間があれば、&lt;code&gt;html()&lt;/code&gt; と &lt;code&gt;update(value)&lt;/code&gt; を動的に追加したり、バリデーション実装して WAF っぽくしたかったです。あと、&lt;code&gt;update(value)&lt;/code&gt; 時に &lt;code&gt;emmit()&lt;/code&gt; を実行したりすると、PySide 側のイベントと連動することができます。予断ですが、Qt には &lt;a href="http://www.pyside.org/docs/pyside/PySide/QtNetwork/QTcpServer.html" target="_blank" title="QTCPSERVER"&gt;QtNetwork.QTCPServer&lt;/a&gt; クラスや &lt;a href="http://www.pyside.org/docs/pyside/PySide/QtNetwork/QTcpSocket.html" target="_blank" title="QTCPSocket"&gt;QTCPSocket&lt;/a&gt; クラスが用意されており、QTCPServer を継承した Web サーバをごりごり書くこともできます (サンプルはこっちの方が多い)。WSGI いいですね！&lt;/p&gt; &lt;p&gt;誰得&lt;/p&gt; &lt;p&gt;さて、明日はいよいよクリスマスイブですね！明日のアドベントカレンダーですが、英語が得意なイケメンアメリカ県民日本人の Google API エキスパートな &lt;a href="http://twitter.com/#!/IanMLewis" target="_blank" title="Ian Lewis"&gt;@IanMLewis&lt;/a&gt; 先生から、素敵なクリスマスプレゼントがあると思います。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-5687900002698508960?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/y5uqcjicoS7QoMTZlBAbYNaCMKE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/y5uqcjicoS7QoMTZlBAbYNaCMKE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/y5uqcjicoS7QoMTZlBAbYNaCMKE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/y5uqcjicoS7QoMTZlBAbYNaCMKE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=TgssH_wZL9Y:oS1VlBMASvg:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=TgssH_wZL9Y:oS1VlBMASvg:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/TgssH_wZL9Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/5687900002698508960/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/12/wsgi-on-qt-pyqt-or-pyside.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/5687900002698508960?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/5687900002698508960?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/TgssH_wZL9Y/wsgi-on-qt-pyqt-or-pyside.html" title="WSGI on Qt (PyQt or PySide)" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_prnhyeZ3SnQ/TRLoH1hcYYI/AAAAAAAAHFk/wQhKExWMnNM/s72-c/step1.png?imgmax=144" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/12/wsgi-on-qt-pyqt-or-pyside.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MNRXw7fCp7ImA9Wx5UF0s.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-6098615905980040511</id><published>2010-10-23T01:32:00.003+09:00</published><updated>2010-10-23T01:38:14.204+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-23T01:38:14.204+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="life" /><category scheme="http://www.blogger.com/atom/ns#" term="music" /><title>高級イヤホン</title><content type="html">&lt;p&gt;
   &amp;quot;NO MUSIC NO LIFE&amp;quot; ですよね。開発のお供に良い音は手放せません。ちなみにいつも聴いているのはラップとレゲトンです。
&lt;/p&gt;
&lt;p&gt;
   去年 BOSE の in-ear を買ったのですが、正直ラップとレゲトンに関しては嫁さんが使っている安価な Audio Technica の方が音質が良い気が・・・。そしてクラシックとジャズは BOSE
   の方が音質が良い気が・・・。ということで、良い音を探す旅に電気屋さんへ。高級イヤホンに関しては、買う前に視聴できる電気屋さんもあるのでお勧めです。今回はラップの音質が一番良いという評価基準で選ぶことにしました。
&lt;/p&gt;
&lt;p&gt;
   かたっぱしから視聴した結果、以下のイヤホンにしぼりました。私的な感想ですが、その他のイヤホンは似たり寄ったり (失礼)。なお、あくまでもラップとレゲトンを聴く人向けの評価になっております。
&lt;/p&gt;
&lt;p&gt;
   まずスペックから評価。
&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;table style="text-align: left;"&gt;
   &lt;thead&gt;
      &lt;tr&gt;
         &lt;th rowspan="2"&gt;
            スペック
         &lt;/th&gt;
         &lt;th&gt;
            BOSE
            &lt;br /&gt;
            IE2
         &lt;/th&gt;
         &lt;th&gt;
            SONY
            &lt;br /&gt;
            MDR-EX510SL
         &lt;/th&gt;
         &lt;th&gt;
            Audio Technica
            &lt;br /&gt;
            ATH-CKS90
         &lt;/th&gt;
      &lt;/tr&gt;
&lt;tr&gt;
         &lt;td style="text-align: center;"&gt;
   &lt;iframe src=
   "http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=FFFFFF&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=333333&amp;amp;lc1=483D8B&amp;amp;t=surgo-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;md=1X69VDGQCMF7Z30FM082&amp;amp;asins=B00432OHEQ"
   style="WIDTH: 120px; HEIGHT: 240px" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;
         &lt;/td&gt;
         &lt;td style="text-align: center;"&gt;
&lt;iframe src=
   "http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=FFFFFF&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=333333&amp;amp;lc1=483D8B&amp;amp;t=surgo-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;md=1X69VDGQCMF7Z30FM082&amp;amp;asins=B00420UAOK"
   style="WIDTH: 120px; HEIGHT: 240px" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;

         &lt;/td&gt;
         &lt;td style="text-align: center;"&gt;
&lt;iframe src=
   "http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;amp;bc1=FFFFFF&amp;amp;IS2=1&amp;amp;bg1=FFFFFF&amp;amp;fc1=333333&amp;amp;lc1=483D8B&amp;amp;t=surgo-22&amp;amp;o=9&amp;amp;p=8&amp;amp;l=as1&amp;amp;m=amazon&amp;amp;f=ifr&amp;amp;md=1X69VDGQCMF7Z30FM082&amp;amp;asins=B003DXBMFI"
   style="WIDTH: 120px; HEIGHT: 240px" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;

         &lt;/td&gt;
&lt;/tr&gt;
   &lt;/thead&gt;
   &lt;tbody&gt;
      &lt;tr&gt;
         &lt;td&gt;
            出力音圧レベル
         &lt;/td&gt;
         &lt;td&gt;
            非公開 ?
         &lt;/td&gt;
         &lt;td&gt;
            106dB/mW
         &lt;/td&gt;
         &lt;td&gt;
            106dB/mW
         &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;
            再生周波数帯域
         &lt;/td&gt;
         &lt;td&gt;
            非公開 ?
         &lt;/td&gt;
         &lt;td&gt;
            5-27000Hz
         &lt;/td&gt;
         &lt;td&gt;
            5-25000Hz
         &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;
            最大入力
         &lt;/td&gt;
         &lt;td&gt;
            非公開 ?
         &lt;/td&gt;
         &lt;td&gt;
            200mW
         &lt;/td&gt;
         &lt;td&gt;
            100mW
         &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;
            インピーダンス
         &lt;/td&gt;
         &lt;td&gt;
            非公開 ?
         &lt;/td&gt;
         &lt;td&gt;
            &lt;p&gt;
               16Ω
            &lt;/p&gt;
         &lt;/td&gt;
         &lt;td&gt;
            &lt;p&gt;
               16Ω
            &lt;/p&gt;
         &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;
            質量
         &lt;/td&gt;
         &lt;td&gt;
            18.5g
         &lt;/td&gt;
         &lt;td&gt;
            7g
         &lt;/td&gt;
         &lt;td&gt;
            9g
         &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;
            特徴
         &lt;/td&gt;
         &lt;td&gt;
            &lt;ul&gt;
               &lt;li&gt;装着感が良い
               &lt;/li&gt;
            &lt;/ul&gt;
         &lt;/td&gt;
         &lt;td&gt;
            &lt;ul&gt;
               &lt;li&gt;不要振動の制振
               &lt;/li&gt;
               &lt;li&gt;広帯域
               &lt;/li&gt;
            &lt;/ul&gt;
         &lt;/td&gt;
         &lt;td&gt;
            &lt;ul&gt;
               &lt;li&gt;圧倒的な重低音
               &lt;/li&gt;
               &lt;li&gt;遮音性が高い
               &lt;/li&gt;
            &lt;/ul&gt;
         &lt;/td&gt;
      &lt;/tr&gt;
   &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;
   BOSE は非公開？SONY 圧勝です。まず、再生周波数帯域が広いので音域は広いですが、人間が聞き取れる可聴域は20000Hzと言われています。つぎに最大入力とインピーダンスですが、 iPod のみの使用しか考えていないので気にしません。共通する特徴はチャンバー
   (耳にさす所の上についてるやつ) が大きいこと。そこで音を増幅するので、大きければ大きいほど低音域がすごい。
&lt;/p&gt;
&lt;p&gt;
   実際に聴いてみてからの評価。
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;BOSE IE2 - &lt;strong&gt;安定&lt;/strong&gt;。中音域から高音域の表現は一番。音の立体感も素晴らしい。でもやっぱりクラシックを聴くのに最高なイヤホン。クラシックは家のホームオーディオでしか聴かない・・・。
   &lt;/li&gt;
   &lt;li&gt;SONY MDR-EX510SL - &lt;strong&gt;忠実&lt;/strong&gt;。たぶん一番原音に忠実。日本らしい製品。ホームオーディオに負けずと劣らない音質。
   &lt;/li&gt;
   &lt;li&gt;Audio Technica ATH-CKS90 - &lt;strong&gt;圧倒&lt;/strong&gt;。高音域は聴き劣りがあるものの、重低音は他を圧倒。イヤホンでこんなラップが聴けるなんて！ちなみにジャズもこれが 1 番いいと思う。
   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   ということで Audio Technica の ATH-CKS90 にしました。こんな自分にピッタリなイヤホン初めてです。装着感も良いし、もう BOSE の in-ear には戻れませんｗ
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-6098615905980040511?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/l_urGYr2bP4ivJBdqnJM1WvMKdE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/l_urGYr2bP4ivJBdqnJM1WvMKdE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/l_urGYr2bP4ivJBdqnJM1WvMKdE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/l_urGYr2bP4ivJBdqnJM1WvMKdE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=21lmhMf8SW4:Zew4BNj0UPA:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=21lmhMf8SW4:Zew4BNj0UPA:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/21lmhMf8SW4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/6098615905980040511/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/10/blog-post.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/6098615905980040511?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/6098615905980040511?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/21lmhMf8SW4/blog-post.html" title="高級イヤホン" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/10/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcNR3o5eip7ImA9Wx5WFUg.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-5420412099656201021</id><published>2010-09-27T11:21:00.001+09:00</published><updated>2010-09-27T11:21:36.422+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-27T11:21:36.422+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Python で Skype にロギングする</title><content type="html">&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/moriyoshi/" target="_blank" title="id:moriyoshi"&gt;id:moriyoshi&lt;/a&gt; さんが "&lt;a href="http://d.hatena.ne.jp/moriyoshi/20100926/1285517353" target="_blank" title="Linux上で動くSkype用のbotを作る方法"&gt;Linux上で動くSkype用のbotを作る方法&lt;/a&gt;" というブログを書かれていたので便乗します。会社で Python から Skype へログを出力するためのハンドラーを試験的に使っていました。便利ですが、利用はお勧めしません。理由は最後に書きます。&lt;/p&gt; &lt;p&gt;コードはこんな感じになります。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# -*- coding: utf-8 -*-
# skype_handler.py

from logging import Handler

try:
    import Skype4Py
    skype = Skype4Py.Skype()
except:
    skype = None

if skype and not skype.Client.IsRunning:
    # Skype が起動してなかったら起動する
    skype.Client.Start()

class SkypeHandler(Handler):
    u"""Skype 用ハンドラ

    Args:
        group_name - Skype group name
        encoding - encoding (Default: 'utf-8')

    この例では、ブックマークしたグループに対してログを出力します。
    `get_chat` を変えたら個人に送信できたりします。
    """

    @staticmethod
    def get_chat(group_name):
        u"""指定したグループ名のチャットをブックマークから取得"""

        if skype is None:
            return None

        for chat in skype.BookmarkedChats:
            if chat.FriendlyName == group_name:
                return chat
        return None

    def __init__(self, group_name, encoding='utf-8'):
        u"""Create SkypeHandler Instanse"""

        Handler.__init__(self)
        self.chat = SkypeHandler.get_chat(group_name)
        self.encoding = encoding

    def send(self, record):
        if self.chat is None:
            return

        message = self.format(record)
        if type(message) is not unicode:
            message = unicode(message, self.encoding)
        self.chat.SendMessage(message)

    def emit(self, record):
        try:
            self.send(record)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)
&lt;/pre&gt;
 &lt;p&gt;使い方はこんな感じ。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# -*- coding: utf-8 -*-
# test.py

import logging
import skype_handler

# Skype チャット名 (ブックマークしたやつ)
CHAT_NAME = 'Test'

# ロガー (`my_logger`) を作成
my_logger = logging.getLogger('my_logger')
my_logger.setLevel(logging.DEBUG)

# Skype ハンドラーを作成
handler = skype_handler.SkypeHandler(CHAT_NAME)

# ロガーに Skype ハンドラーを追加
my_logger.addHandler(handler)

my_logger.debug(u"ほげ")
&lt;/pre&gt;
 &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_prnhyeZ3SnQ/TJ__rXsU90I/AAAAAAAAHFI/ruffJol4rp0/skype_handler.PNG"&gt;&lt;img src="http://lh4.ggpht.com/_prnhyeZ3SnQ/TJ__rtrKWwI/AAAAAAAAHFM/hjkBKHI758I/zrtn_002n38b0b017_tn.jpg?imgmax=400" style="DISPLAY: block; MARGIN-LEFT: auto; WIDTH: 276px; MARGIN-RIGHT: auto; HEIGHT: 400px; TEXT-ALIGN: center" height="400" width="276"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Skype にログがはかれます。時間はリアルタイムだし、ある程度負荷をかけてもちゃんと出力してくれるし、サーバ毎に skype ユーザ変えるとログ管理も簡単だし、、、。&lt;/p&gt; &lt;p&gt;ですが！使わないほうがいいです。最初はさくさく動いてくれてて問題なかったのですが、しばらく使っていると子ノードがいっぱいになったのか、ブラジルとかコートジボアールとかからもっすごい量のパケットを受信し始めちゃいました orz でっネットワークに負荷がかかり "やめろ" とお叱りが・・・。自宅で使ってる分にはなんの問題もでてないですが、会社でやっちゃうとネットワーク管理者に怒られるかも。&lt;/p&gt; &lt;p&gt;是非使ってみてくださいｗ&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-5420412099656201021?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ad3LB7JboaJl9J3hp3dR5aPhJg8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ad3LB7JboaJl9J3hp3dR5aPhJg8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ad3LB7JboaJl9J3hp3dR5aPhJg8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ad3LB7JboaJl9J3hp3dR5aPhJg8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=NUBJ1b9R5LA:zr6X-bykV58:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=NUBJ1b9R5LA:zr6X-bykV58:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/NUBJ1b9R5LA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/5420412099656201021/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/09/python-skype.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/5420412099656201021?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/5420412099656201021?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/NUBJ1b9R5LA/python-skype.html" title="Python で Skype にロギングする" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_prnhyeZ3SnQ/TJ__rtrKWwI/AAAAAAAAHFM/hjkBKHI758I/s72-c/zrtn_002n38b0b017_tn.jpg?imgmax=400" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/09/python-skype.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUGRXk-eip7ImA9Wx5QFUQ.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-7508232701512978380</id><published>2010-09-04T17:40:00.001+09:00</published><updated>2010-09-04T17:50:24.752+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-04T17:50:24.752+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="pyside" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><category scheme="http://www.blogger.com/atom/ns#" term="pyqt" /><title>PySide for Windows</title><content type="html">&lt;p&gt;&lt;img src="http://lh6.ggpht.com/_prnhyeZ3SnQ/TIIHsw7Uk8I/AAAAAAAAHEs/ySuzK8jBMQI/pyside.png" style="WIDTH: 199px; DISPLAY: inline; FLOAT: left; HEIGHT: 102px" title="PySide" height="102" width="199" alt="PySide"/&gt;&lt;a href="http://www.pyside.org/" target="_blank" title="PySide"&gt;PySide&lt;/a&gt; の &lt;a href="http://www.pyside.org/2010/08/windows-version-released/" target="_blank" title="Windows version released"&gt;Windows 版が公開&lt;/a&gt;されました。PySide は Qt (Nokia 製のクロスプラットフォームな GUI ツールキット) の Python binding です。もともと Qt の Python binding は &lt;a href="http://www.riverbankcomputing.co.uk/software/pyqt/" target="_blank" title="PyQt"&gt;PyQt&lt;/a&gt; というのがありました。Qt のライセンスは 4.5 から GPL / LGPL / 商用ライセンス (&lt;a href="http://www.sra.co.jp/qt/licence/" target="_blank" title="Qt ライセンス"&gt;日本での価格&lt;/a&gt;) になったのですが、PyQt の&lt;a href="http://www.riverbankcomputing.co.uk/software/pyqt/license" target="_blank" title="License"&gt;ライセンス&lt;/a&gt;は GPL / 商用ライセンスとなっています。商用ライセンスで使うためには、けっこう高いお金を払わないといけないです。GPL だと、PyQt を利用するすべてのアプリケーションは GPL にしないといけません。ML で "金を払うから LGPL にしろ！" と言ってる方もいらっしゃいましたね。でもいろいろと難しかったようで、Qt 作者の Nokia さんが LGPL 対応の Python binding をフルスクラッチしたのが PySide です。&lt;/p&gt; &lt;p&gt;さっそく開発している PyQt アプリケーションの branche を切って、PySide 化始めました。これを機に、もっと Qt と Python が流行ればいいと思います。&lt;/p&gt; &lt;p&gt;PySide for Windows な記事&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://philosy.com/blog/2010/09/02/pyside-for-windows/" target="_blank" title="PySide for Windows"&gt;philo 式さんのブログ&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://slashdot.jp/~greentea/journal/485583" target="_blank" title="新しい、Python用Qtバインディング"&gt;Slashdot&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-7508232701512978380?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cuw13kelBHn0Nr6TgECFlnQpDQE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cuw13kelBHn0Nr6TgECFlnQpDQE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cuw13kelBHn0Nr6TgECFlnQpDQE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cuw13kelBHn0Nr6TgECFlnQpDQE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=sSyRl8lItkI:aDZ9zRaczdA:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=sSyRl8lItkI:aDZ9zRaczdA:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/sSyRl8lItkI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/7508232701512978380/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/09/pyside-for-windows.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7508232701512978380?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/7508232701512978380?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/sSyRl8lItkI/pyside-for-windows.html" title="PySide for Windows" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_prnhyeZ3SnQ/TIIHsw7Uk8I/AAAAAAAAHEs/ySuzK8jBMQI/s72-c/pyside.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/09/pyside-for-windows.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEMQnYzfCp7ImA9Wx5REU0.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-547439433022582654</id><published>2010-08-17T20:40:00.001+09:00</published><updated>2010-08-18T12:54:43.884+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-18T12:54:43.884+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="py2app" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="innosetup" /><category scheme="http://www.blogger.com/atom/ns#" term="py2exe" /><category scheme="http://www.blogger.com/atom/ns#" term="pyqt" /><title>PyQt でクロスプラットフォームなデスクトップアプリケーションを</title><content type="html">&lt;p&gt;ここ何ヶ月かデスクトップアプリケーションにどっぷりな感じです。パッケージングをもっと簡単にしたい！ということで色々と試行錯誤しておりました。linux, mac はいい感じですが、Windows は・・・ &lt;a href="http://www.py2exe.org/" target="_blank" title="py2exe"&gt;py2exe&lt;/a&gt; でフリージングのみしかしていませんでした。配布とインストールは自動解凍書庫、アップデート、アンインストールは・・・。そこで今回 (やっと) 覚えたのが &lt;a href="http://www.jrsoftware.org/" target="_blank" title="Inno Setup"&gt;Inno Setup&lt;/a&gt; や &lt;a href="http://wix.sourceforge.net/" target="_blank" title="Windows Installer XML (WiX) toolset"&gt;WiX&lt;/a&gt; といった Windows 用のパッケージビルダです。備忘録がてら、Python でのパッケージングをまとめてみました。&lt;/p&gt; &lt;h4&gt;パッケージングについて&lt;/h4&gt; &lt;p&gt;大きく 2 つのフェーズに分かれています。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;フリージング: Python バンドルや他の必要なライブラリーを寄せ集め、実行可能形式にまとめます。 &lt;br/&gt;Windows と OS X については以下のライブラリでフリージングします。 &lt;br/&gt;&lt;ul&gt; &lt;li&gt;Windows 用: &lt;a href="http://www.py2exe.org/" target="_blank" title="py2exe"&gt;py2exe&lt;/a&gt;&lt;/li&gt; &lt;li&gt;OS X 用: &lt;a href="http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html" target="_blank" title="py2app - Create standalone Mac OS X applications with Python"&gt;py2app&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;br/&gt;Linux を含むクロスプラットフォームなフリージングができる &lt;a href="http://cx-freeze.sourceforge.net/" target="_blank" title="cx_Freeze"&gt;cx_Freeze&lt;/a&gt; というのもあります。&lt;/li&gt; &lt;li&gt;ディストリビューションのビルド&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;Windows: &lt;a href="http://msdn.microsoft.com/en-us/library/aa372866.aspx" target="_blank" title="Windows Installer"&gt;Microsoft Windows Installer&lt;/a&gt; はアップグレード、アンインストール、トランザクション処理を使った複数パッケージの管理とかの便利機能を持っています。&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://wix.sourceforge.net/" target="_blank" title="Windows Installer XML (WiX) toolset"&gt;WiX&lt;/a&gt; (&lt;a href="http://ja.wikipedia.org/wiki/WiX" target="_blank" title="WiX"&gt;Wikipedia&lt;/a&gt;): MSI 形式でビルドするための MS 製のオープンソースツールです。WXS という XML ファイルを作成し、それを元にビルドします。&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.jrsoftware.org/isinfo.php" target="_blank" title="Inno Setup"&gt;Inno Setup&lt;/a&gt; (&lt;a href="http://inno-setup.sidefeed.com/" target="_blank" title="Inno Setup 日本語デベロッパーズガイド"&gt;日本ドキュメント&lt;/a&gt;): Windows インストーラ (Setup.exe) を作成するオープンソースツールです。Delphi で書かれています。&lt;/li&gt; &lt;li&gt;&lt;a href="http://nsis.sourceforge.net/" target="_blank" title="Nullsoft Scriptable Install System"&gt;NSIS&lt;/a&gt; (&lt;a href="http://ja.wikipedia.org/wiki/Nullsoft_Scriptable_Install_System" target="_blank" title="Nullsoft Scriptable Install System"&gt;Wikipedia&lt;/a&gt;): 多機能。スクリプト駆動型のWindows用インストールシステム。Mozilla, Google, BitTorrent などにも使われています。&lt;/li&gt; &lt;li&gt;他にもあるかもです。&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;OS X: &lt;a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man1/hdiutil.1.html" target="_blank" title="HDIUTIL(1)"&gt;hdiutil&lt;/a&gt;: py2app でできた *.app を *.dmg にしてくれるらしいです (使ったことありません)。&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h4&gt;クロスプラットフォームな setup.py の書き方&lt;/h4&gt; &lt;p&gt;Windows と OS X のフリージングは、py2exe と py2app があるので簡単です。プラットフォーム情報を取得し、各プラットフォームに対してフリージングします。いろんなコードを見ましたが、切り分けるコードは大きく 2 種類ありました。私は簡単なので前者を使っています。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
import sys

if sys.platform == 'win32':
    u"""Windows 用のフリージング"""

    import py2exe

    # 処理

if sys.platform == 'darwin':
    u"""OS X 用のフリージング"""

    import py2app

    # 処理

if sys.platform == 'linux2':
    u"""Linux 用のビルド"""

    import subprocess

    u"""
    makeself 等でインストーラを作成するコマンドを実行::
    
        ret = subprocess.Popen("makeself ...")
        ret.wait()
    
    cx_Freeze でもいいと思います。
    """
&lt;/pre&gt;
 
&lt;pre class="prettyprint"&gt;
import platform

if platform.system() in ['Windows', 'Microsoft']:
    u"""Windows 用のフリージング"""

    # 省略

if platform.system() == 'Darwin':
    u"""OS X 用のフリージング"""

    # 省略

if platform.system() == 'Linux':
    u"""Linux 用のビルド"""

    # 省略
&lt;/pre&gt;
 &lt;hr/&gt; &lt;h4&gt;Inno Setup によるディストリビューションのビルド&lt;/h4&gt; &lt;p&gt;Inno Setup は distutils の拡張モジュールが pypi に提供されています。なので、上記の setup.py にちょっと追加すれば、Windows についてはディストリビューションのビルドがかなりお手軽になります。&lt;/p&gt; &lt;h5&gt;環境の構築&lt;/h5&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.microsoft.com/japan/msdn/vstudio/2008/product/express/" target="_blank" title="Visual Studio 2008 Express Edition with Service Pack 1 のダウンロード"&gt;Visual C++ (Windows Platform SDK)&lt;/a&gt;: py2exe にも必要&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.jrsoftware.org/isdl.php#qsp" target="_blank" title="Inno Setup QuickStart Pack"&gt;Inno Setup QuickStart Pack&lt;/a&gt;: IStools Script Editor 等のサードパーティアドオンなどが含まれます&lt;/li&gt; &lt;li&gt;&lt;a href="http://pypi.python.org/pypi/innosetup/" target="_blank" title="innosetup"&gt;innosetup Pythono ライブラリ&lt;/a&gt;: Inno Setup 用ライブラリ&lt;/li&gt; &lt;/ul&gt; &lt;h5&gt;setup.py の書き方&lt;/h5&gt; &lt;p&gt;PyQt アプリケーションのディレクトリ構成は以下のようにしました。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;path/to/project: プロジェクトディレクトリ&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;dist: パッケージが保存されるディレクトリ (自動的に作成されます)&lt;/li&gt; &lt;li&gt;test: PyQt アプリケーションディレクトリ&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;media: アイコンファイルなどのリソースを保存するディレクトリ&lt;/li&gt; &lt;li style="LIST-STYLE-TYPE: none"&gt; &lt;ul&gt; &lt;li&gt;test.ico: アイコンファイル&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;main.py: メインスクリプト&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;setup.py: パッケージング用スクリプト&lt;/li&gt; &lt;li&gt;README: アプリケーション概要を記載したファイル (Windows の場合は cp932 に保存)&lt;/li&gt; &lt;li&gt;LICENSE: ライセンスを記載したファイル (cp932)&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; 
&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python2.6
# -*- coding: utf-8 -*-

import os
import sys, subprocess
from distutils.core import setup

########################################
# コンパイルオプション設定             #
########################################

# バイナリ名
NAME = u"test"

# バージョン情報
VERSION = "1.0.0"

# 著作権
AUTHOR = "Kosei Kitahara"

# メール
EMAIL = "mail@example.com"

# URL
u"""
AppID を生成するように用いられるため、アプリケーション毎にユニークにする
"""
URL = "http://example.com/test"

# パッケージ 概要
DESCRIPTION = u"テスト用アプリケーション"

# Python バイトコードの最適化オプション (0: None, 1: -O, 2: -OO)
OPTIMIZE = 2

# 圧縮オプション (0: 圧縮しない, 1: 圧縮する)
COMPRESSED = 1

# バンドルオプション (1: 単独, 3: 個別)
BUNDLE_FILES = 3

# 依存ライブラリの解決
INCLUDES = ["sip", "ctypes", ]
EXCLUDES = ["_ssl", "tcl", "tkinter", "Tkconstants", "Tkinter", ]
DLL_EXCLUDES = ["tcl84.dll", "tk84.dll", ]

# ディレクトリ, ファイルなど
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
APPLICATION_DIR = os.path.join(BASE_DIR, "test")
DIST_DIR = os.path.join(BASE_DIR, "dist")

MAIN_SCRIPT_NAME = os.path.join(APPLICATION_DIR, "main.py")
ICON_FILE_NAME = os.path.join(APPLICATION_DIR, "media", "test.ico")
LICENSE_FILE_NAME = os.path.join(BASE_DIR, "LICENSE")

########################################
# ユーティリティ関数                   #
########################################

def get_win32ui_files():
    u"""win32ui 依存 dll の取得"""

    import win32ui
    win32ui_dir = os.path.dirname(win32ui.__file__)
    return [os.path.join(win32ui_dir, i) for i in [
        "mfc90.dll", 
        "mfc90u.dll", 
        "mfcm90.dll", 
        "mfcm90u.dll", 
        "Microsoft.VC90.MFC.manifest", ]]
WIN32UI_MFCFILES = get_win32ui_files()

def get_pyqt4_imageformats_plugin_files():
    u"""PyQt4 の画像コーデック依存 dll の取得"""

    import PyQt4
    pyqt4_dir = os.path.dirname(PyQt4.__file__)
    return [os.path.join(pyqt4_dir, "plugins", "imageformats", i) for i in [
        "qgif4.dll",
        "qico4.dll",
        "qjpeg4.dll",
        "qmng4.dll",
        "qsvg4.dll",
        "qtiff4.dll", ]]
PYQT4_IMAGEFORMATS = get_pyqt4_imageformats_plugin_files()

########################################
# ビルドスクリプト                     #
########################################

# Linux, OS X は省略
if sys.platform == 'win32':
    u"""Windows 用のフリージング"""

    import py2exe, innosetup

    # py2exe, innosetup 共通ビルドオプション
    DATA_FILES = [
            ("Microsoft.VC90.MFC", WIN32UI_MFCFILES), 
            ("imageformats", PYQT4_IMAGEFORMATS), ]
    ICON_RESOURCES = [(1, ICON_FILE_NAME), ]
    PY2EXE_OPTIONS = {
            "includes": INCLUDES,
            "excludes": EXCLUDES,
            "dll_excludes": DLL_EXCLUDES,
            "compressed": COMPRESSED,
            "optimize": OPTIMIZE,
            "bundle_files": BUNDLE_FILES, }

    # innosetup ビルドオプション
    u"""
    'inno_script' は、.iss ファイル名を指定することもできますが、
    デフォルトでも用意されているので、大変便利です。
    """
    INNOSETUP_OPTIONS = {
            "inno_script": innosetup.DEFAULT_ISS, 
            "bundle_vcr": True, 
            "zip": False, }

    setup(
            name=NAME,
            version=VERSION,
            license=LICENSE_FILE_NAME,
            author=AUTHOR,
            author_email=EMAIL,
            description=DESCRIPTION,
            url=URL,
            data_files=DATA_FILES,
            options={
                    "py2exe" : PY2EXE_OPTIONS,
                    "innosetup": INNOSETUP_OPTIONS},
            windows=[{
                    "script" : MAIN_SCRIPT_NAME, 
                    "icon_resources": ICON_RESOURCES}], 
            zipfile="test.lib", )
&lt;/pre&gt;
 &lt;p&gt;py2exe の設定を継承してくれるので、大変便利ですね。&lt;/p&gt; &lt;h5&gt;パッケージング処理の実行&lt;/h5&gt; &lt;p&gt;以下のコマンドを実行すると、パッケージングしてくれます。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
python setup.py innosetup
&lt;/pre&gt;
 &lt;p&gt;もちろん &lt;code&gt;setup.py py2exe&lt;/code&gt;も動作します。innosetup の run メソッドは py2exe を継承しており、dist ディレクトリに作成するライブラリや実行ファイルは py2exe と同様です。それとは別に以下のファイルが作成されます。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Microsoft.VC90.CRT.manifest&lt;/li&gt; &lt;li&gt;distutils.iss: インストーラ作成用 ISS ファイル&lt;/li&gt; &lt;li&gt;test-1.0.0-setup.exe: インストーラファイル。ファイル名は settings.py で設定した [アプリケーション名]-[バージョン]-setup.exe になります。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;実行すると Inno Setup Compiler が自動的に起動し、作成した distutils.iss ファイルを元にインストーラーが作成されます。途中でエラーが出たら、innosetup.py を修正し、出力する ISS ファイルを変更しましょうｗ&lt;/p&gt; &lt;p&gt;ちなみに、私の環境では以下を修正しました。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
218c218
&amp;lt;             return win32api.LoadResource(handle, restype, name).decode('utf_8')
---
&amp;gt;             return win32api.LoadResource(handle, restype, name).decode('utf-8')
525c525
&amp;lt;             iss_metadata['MinVersion'] = '5.0,4.0'
---
&amp;gt;             iss_metadata['MinVersion'] = '0,5.0'
546c546
&amp;lt;             fp.write('%s=%s\n' % (k, iss_metadata[k], ))
---
&amp;gt;             fp.write(unicode('%s=%s\n' % (k, iss_metadata[k], )).encode("utf-8"))
779c779
&amp;lt;             fp.write('#define %s "%s"\n' % (k, consts[k], ))
---
&amp;gt;             fp.write(unicode('#define %s "%s"\n' % (k, consts[k], )).encode("utf-8"))
&lt;/pre&gt;
 &lt;p&gt;これでデスクトップアプリケーションの配布がかなり楽になりましたよ！ユニコードインストーラなどについてはもうちょっと調べる必要がありますね・・・。&lt;/p&gt; &lt;h4&gt;追記 (2010-08-18)&lt;/h4&gt; &lt;p&gt;試してないですが、&lt;a href="http://pypi.python.org/pypi/bdist_nsi/" target="_blank" title="bdist_nsi"&gt;bdist_nsi&lt;/a&gt; という NSS I 用の distutils 拡張モジュールが pypi に登録されていました。&lt;a href="http://github.com/amorilia/bdist_nsi/blob/master/bdist_nsi/bdist_nsi.py" target="_blank" title="/bdist_nsi/bdist_nsi.py at master from amorilia's bdist_nsi - GitHub"&gt;ソース&lt;/a&gt;を見ると、Python 3 にも対応しており (Python 2 は 3 へ変換)、py2exe は使ってないようですね。これはよさげ！&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-547439433022582654?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sqXMTpvCZDGrVXqKHbzFX_z_boU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sqXMTpvCZDGrVXqKHbzFX_z_boU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sqXMTpvCZDGrVXqKHbzFX_z_boU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sqXMTpvCZDGrVXqKHbzFX_z_boU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=C6UnsUVkldI:kxGRO_Eikyk:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=C6UnsUVkldI:kxGRO_Eikyk:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/C6UnsUVkldI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/547439433022582654/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/08/pyqt.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/547439433022582654?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/547439433022582654?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/C6UnsUVkldI/pyqt.html" title="PyQt でクロスプラットフォームなデスクトップアプリケーションを" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/08/pyqt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEACRHs8eyp7ImA9Wx5SE0k.&quot;"><id>tag:blogger.com,1999:blog-18400048.post-8499868716543380767</id><published>2010-08-09T17:32:00.001+09:00</published><updated>2010-08-09T17:32:45.573+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-09T17:32:45.573+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="windows" /><category scheme="http://www.blogger.com/atom/ns#" term="py2exe" /><category scheme="http://www.blogger.com/atom/ns#" term="pyqt" /><title>PyQt を py2exe でフリージング</title><content type="html">&lt;h4&gt;標準的なフリージング&lt;/h4&gt; 
&lt;pre class="prettyprint"&gt;
# setup.py

import py2exe
from distutils.core import setup

py2exe_options = {
    "compressed": 1,　# 圧縮する
    "optimize": 2,
    "bundle_files": 3,
    "includes" : ["sip",]
}
setup(
    options={"py2exe" : py2exe_options},
    windows=[{"script" : "main.py"}], # PyQt ファイル
    zipfile="[zipped.lib　ファイル名]",
)
&lt;/pre&gt;
 &lt;p&gt;私の環境 (XP, Py2.6.4) では、 &lt;code&gt;py2exe_options&lt;/code&gt; の &lt;code&gt;bundle_files&lt;/code&gt; は 3 (分割ファイル) じゃないと動作しませんでした。&lt;/p&gt; &lt;h4&gt;jpeg や gif 等の画像を取り扱う場合&lt;/h4&gt; &lt;p&gt;PyQt は bmp や png 以外の画像形式を標準でサポートしていません。その他のフォーマットはプラグインとして提供されています。プラグイン (dll) をフリージングしたファイル配下のディレクトリーに保存する必要があります。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# setup.py

import os
import py2exe
from distutils.core import setup

# 任意のフォーマットの dll を追加。特にアイコンは必要かも
IMAGELIB_DIR = r"C:\path\to\python\Lib\site-packages\PyQt4\plugins\imageformats"
imgfiles = [os.path.join(IMAGELIB_DIR, i) for i in [
    "qgif4.dll",
    "qico4.dll",
    "qjpeg4.dll",
    "qmng4.dll",
    "qsvg4.dll",
    "qtiff4.dll",]]

data_files = [
    ("imageformats", imgfiles), 
]

py2exe_options = {
    "compressed": 1,
    "optimize": 2,
    "bundle_files": 3,
    "includes" : ["sip",]
}

setup(
    data_files = data_files,
    options={"py2exe" : py2exe_options},
    windows=[{"script" : "main.py"}], # PyQt ファイル
    zipfile="[zipped.lib　ファイル名]",
)
&lt;/pre&gt;
 &lt;h4&gt;win32ui を利用する場合&lt;/h4&gt; &lt;p&gt;MFC (Microsoft Foundation Classes) の dll が必要 (&lt;a href="http://www.py2exe.org/index.cgi/Py2exeAndWin32ui" target="_blank" title="Py2exeAndWin32ui"&gt;本家ドキュメント&lt;/a&gt;)。&lt;/p&gt; 
&lt;pre class="prettyprint"&gt;
# setup.py

import os
import py2exe
from distutils.core import setup

WIN32UI_DIR = r"C:\path\to\python\Lib\site-packages\pythonwin"
mfcfiles = [os.path.join(WIN32UI_DIR, i) for i in [
    "mfc90.dll", 
    "mfc90u.dll", 
    "mfcm90.dll", 
    "mfcm90u.dll", 
    "Microsoft.VC90.MFC.manifest"]]

IMAGELIB_DIR = r"C:\path\to\python\Lib\site-packages\PyQt4\plugins\imageformats"
imgfiles = [os.path.join(IMAGELIB_DIR, i) for i in [
    "qgif4.dll",
    "qico4.dll",
    "qjpeg4.dll",
    "qmng4.dll",
    "qsvg4.dll",
    "qtiff4.dll",]]

data_files = [
    ("Microsoft.VC90.MFC", mfcfiles), 
    ("imageformats", imgfiles), 
]

py2exe_options = {
    "compressed": 1,
    "optimize": 2,
    "bundle_files": 3,
    "includes" : ["sip",　"ctypes",] # ctypes を利用している場合は追加する
}

setup(
    data_files = data_files,
    options={"py2exe" : py2exe_options},
    windows=[{"script" : "main.py"}], # PyQt ファイル
    zipfile="[zipped.lib　ファイル名]",
)
&lt;/pre&gt;
 &lt;p&gt;py2exe は利用しないライブラリーなども取り込まれるらしく、ちょっとファイルが大きくなってしまいます。私の環境では簡単なウィジェットでも 11 M ぐらいになりました。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18400048-8499868716543380767?l=surgo.jp' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/C5FqJtoVEWK5BSB13ffyXzXrY3Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/C5FqJtoVEWK5BSB13ffyXzXrY3Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/C5FqJtoVEWK5BSB13ffyXzXrY3Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/C5FqJtoVEWK5BSB13ffyXzXrY3Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/surgo/posts?a=pT3AC82FgdM:hQgHRN-6V0c:j5ujfbmacDE"&gt;&lt;img src="http://feeds.feedburner.com/~ff/surgo/posts?i=pT3AC82FgdM:hQgHRN-6V0c:j5ujfbmacDE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/surgo/posts/~4/pT3AC82FgdM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://surgo.jp/feeds/8499868716543380767/comments/default" title="コメントの投稿" /><link rel="replies" type="text/html" href="http://surgo.jp/2010/08/pyqt-py2exe.html#comment-form" title="0 件のコメント" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/8499868716543380767?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18400048/posts/default/8499868716543380767?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/surgo/posts/~3/pT3AC82FgdM/pyqt-py2exe.html" title="PyQt を py2exe でフリージング" /><author><name>Kosei Kitahara</name><uri>https://profiles.google.com/108672473782199571535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-0EG-BokiPco/AAAAAAAAAAI/AAAAAAAAHR8/oC656qnC57o/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://surgo.jp/2010/08/pyqt-py2exe.html</feedburner:origLink></entry></feed>

