<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1014022074285403080</id><updated>2024-09-10T07:10:56.164+09:00</updated><category term="python"/><category term="flask"/><category term="whoosh"/><category term="全文検索"/><category term="flask-extensions"/><category term="furl"/><category term="tips"/><category term="algorithm"/><category term="appengine"/><category term="gae"/><category term="hack-a-thon"/><category term="http"/><category term="jsonp"/><category term="juno"/><category term="kestrel"/><category term="memcached"/><category term="o&#39;reilly"/><category term="pep8"/><category term="pylucene"/><category term="streaming"/><category term="test"/><category term="unittest"/><category term="web"/><category term="zen"/><category term="オーバーロード"/><category term="本"/><title type='text'>Study Python</title><subtitle type='html'>Pythonについて書いてく。&#xa;蛇使いを目指す中年です。&#xa;マイクロフレームワークFlaskが好き。</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-5867831479997474019</id><published>2012-02-12T21:20:00.001+09:00</published><updated>2012-02-12T21:24:37.626+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="furl"/><category scheme="http://www.blogger.com/atom/ns#" term="http"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>HTTPリクエストパラメータを抽出する</title><content type='html'>テストケースのないシステムをメンテンナンスをすることもあると思います。

HTTPで提供するAPIのテストケースを作成しなければならない場合は、
とにかくログを投げまくってテストするなどの方法が有効だったりするんですが、
(まあそもそもテストケースがないシステムについてのツッコミは受け付けません)

ログから有効なテストケースを抽出するために、
リクエストパラメータの組み合わせによるURLの抽出なんかが一つの案です。

ということでログからリクエストパラメータの抽出を行うスクリプトをざっくり書いてみました。


&lt;pre class=&quot;prettyprint&quot;&gt;

import sys
from collections import defaultdict
from furl import furl

sampling_urls = defaultdict(dict)

for line in sys.stdin:
    url = line.strip()
    f = furl(url)
    param_keys = tuple(sorted(f.args.keys()))
    param_combination = sampling_urls[str(f.path)]
    if param_keys not in param_combination:
        param_combination[param_keys] = url

for path, param_combination in sampling_urls.items():
    for combination, sample_url in param_combination.items():
        print path, combination, sample_url

&lt;/pre&gt;



インプットログ
&lt;pre class=&quot;prettyprint&quot;&gt;
http://xxx/api?param1=a&amp;amp;param2=a
http://xxx/api?param1=b&amp;amp;param2=b
http://xxx/api?param1=c&amp;amp;param2=c&amp;amp;param3=c
http://xxx/api?param1=d&amp;amp;param2=d&amp;amp;param3=c
http://xxx/api?param1=e&amp;amp;param2=d&amp;amp;param4=d
http://xxx/api2?param1=e&amp;amp;param2=d&amp;amp;param4=d
http://xxx/api3?param1=e&amp;amp;param2=d&amp;amp;param4=d
&lt;/pre&gt;

実行結果
&lt;pre class=&quot;prettypring&quot;&gt;
$ python sampling.py &lt; input 
/api2 (&#39;param1&#39;, &#39;param2&#39;, &#39;param4&#39;) http://xxx/api2?param1=e&amp;amp;param2=d&amp;amp;param4=d
/api (&#39;param1&#39;, &#39;param2&#39;, &#39;param3&#39;) http://xxx/api?param1=c&amp;amp;param2=c&amp;amp;param3=c
/api (&#39;param1&#39;, &#39;param2&#39;, &#39;param4&#39;) http://xxx/api?param1=e&amp;amp;param2=d&amp;amp;param4=d
/api (&#39;param1&#39;, &#39;param2&#39;) http://xxx/api?param1=a&amp;amp;param2=a
/api3 (&#39;param1&#39;, &#39;param2&#39;, &#39;param4&#39;) http://xxx/api3?param1=e&amp;amp;param2=d&amp;amp;param4=d
&lt;/pre&gt;

前に記事に書いたfurlというurlパーサーを利用しています。

itertools.combinationsとかを使わないとできないかと思いましたが、
tupleを辞書のキーにすることで簡単にできました。

valueが空の時の処理などは必要に応じて作成する必要がありますが、
それなりに有効そうです。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/5867831479997474019/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2012/02/http.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/5867831479997474019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/5867831479997474019'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2012/02/http.html' title='HTTPリクエストパラメータを抽出する'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-2810312803694380171</id><published>2012-01-30T22:38:00.002+09:00</published><updated>2012-01-30T22:38:50.314+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="furl"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>furlを使ってみた</title><content type='html'>ブログを久しく書いていないので、ライブラリの覚書を少しずつ書くことにする。&lt;br /&gt;
&lt;br /&gt;
最近少し話題になったfurlについて使い方を簡単に書いておく。&lt;br /&gt;
&lt;br /&gt;
インストールはいつものように&lt;br /&gt;
easy_install furl&lt;br /&gt;
pip install furl&lt;br /&gt;
でできる。&lt;br /&gt;
&lt;br /&gt;
使ってみたログを書いてみる

&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
&gt;&gt;&gt; from furl import furl
&gt;&gt;&gt; url = furl(&quot;http://pypi.python.org/pypi?%3Aaction=search&amp;amp;term=test&amp;amp;submit=search&quot;)
&gt;&gt;&gt; url.host
&#39;pypi.python.org&#39;
&gt;&gt;&gt; url.port
80
&gt;&gt;&gt; url.query
Query(&#39;term=test&amp;amp;%3Aaction=search&amp;amp;submit=search&#39;)
&gt;&gt;&gt; url.query.params
{&#39;term&#39;: &#39;test&#39;, &#39;:action&#39;: &#39;search&#39;, &#39;submit&#39;: &#39;search&#39;}
&gt;&gt;&gt; url.args
{&#39;term&#39;: &#39;test&#39;, &#39;:action&#39;: &#39;search&#39;, &#39;submit&#39;: &#39;search&#39;}
&lt;/pre&gt;
cgi.parse_qsとかよりは結構使いやすい気がするが一点気になることが・・・
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&gt;&gt;&gt; url = furl(&quot;http://pypi.python.org/pypi?%3Aaction=search&amp;amp;term=test&amp;amp;submit=search&amp;amp;term=test2&quot;)
&gt;&gt;&gt; url.args
{&#39;term&#39;: &#39;test&#39;, &#39;:action&#39;: &#39;search&#39;, &#39;submit&#39;: &#39;search&#39;}
&gt;&gt;&gt; url.query.params
{&#39;term&#39;: &#39;test&#39;, &#39;:action&#39;: &#39;search&#39;, &#39;submit&#39;: &#39;search&#39;}
&lt;/pre&gt;
リクエストパラメータに同じキーのものが複数入っていた場合、&lt;br /&gt;
どちらか一方しかargsに入らない。&lt;br /&gt;
&lt;br /&gt;
HTTPの仕様では同じキーに別の値を入れることができて、&lt;br /&gt;
サーバ側では配列で受け取れるようになっているのだとばっかり。&lt;br /&gt;
&lt;br /&gt;
そのようなリクエストは、このままでは正しくparseできない。(やり方発見できず)&lt;br /&gt;
簡単に使えるし、良い感じなだけに惜しいなー。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/2810312803694380171/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2012/01/furl.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2810312803694380171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2810312803694380171'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2012/01/furl.html' title='furlを使ってみた'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-6289352544954614791</id><published>2011-10-23T00:08:00.004+09:00</published><updated>2011-10-23T00:33:16.487+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="hack-a-thon"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>第12回Python mini Hack-a-thon参加報告</title><content type='html'>Python mini Hack-a-thonに参加してきました。&lt;br /&gt;
昼食時にPyConJPの寺田さんや世界の小宮さんの話を聴けるなど、&lt;br /&gt;
非常に楽しい一日になりました。&lt;br /&gt;
&lt;br /&gt;
で、重要なHack-a-thonで何をやっていたかというと、&lt;br /&gt;
まずPython ORMの調査&lt;br /&gt;
これはstormというORMを使ってみるというところで進めていました。&lt;br /&gt;
とあるRDBで使いたいのだけれどそのRDBでの利用についての記述が一切ない。&lt;br /&gt;
試したかったけど自分のマシンにそのRDBをインストールするのが嫌だったので、&lt;br /&gt;
SqlAlchemy、elixir、sqlobjectでサンプルコードを書いてsqliteにデータを入れたり消したりということを試して遊んでました。&lt;br /&gt;
&lt;br /&gt;
昼食後眠くなり、ORMの調査は放棄して、&lt;br /&gt;
ProjectEulerの問題解いたり、自分のgae上のwebアプリ直したりしてた。&lt;br /&gt;
最後の3時間くらいで成果発表用の何かを作成しようと思って、&lt;br /&gt;
akb48のメンバーを検索するモジュールを書いてました。&lt;br /&gt;
&lt;br /&gt;
pyfesでのmoriyoshiさんの発表に感銘を受けたので完全にパクリです。詳細は&lt;a href=&quot;http://d.hatena.ne.jp/moriyoshi/20111015/1318709627&quot;&gt;こちら&lt;/a&gt;&lt;br /&gt;
moriyoshiさんはperlのacmeの移植だそうなんで、移植のパクリです。お恥ずかしい。&lt;br /&gt;
&lt;br /&gt;
せっかくなんでgithubに上げました。(ドキュメント空です。すんません。後追加します。)&lt;br /&gt;
&lt;a href=&quot;https://github.com/shocking-noise/akb48&quot;&gt;https://github.com/shocking-noise/akb48&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
実行方法は下記の通り&lt;br /&gt;
1.必要なモジュールのインストール(BeautifulSoup、yaml)&lt;br /&gt;
2.scraperを実行してyaml生成&lt;br /&gt;
3.akb48モジュールをインポートして利用&lt;br /&gt;
&lt;br /&gt;
こだわりポイントは誕生日から今日の年齢を算出するところです。&lt;br /&gt;
(ググッてコピペレベルですが)&lt;br /&gt;
&lt;br /&gt;
発表後の指摘として、yamlは邪道だという話があったので、&lt;br /&gt;
クラスを生成するコードジェネレータ作るように修正したいです。&lt;br /&gt;
(本当のファンなら一字一字コードを打つべきという意見も・・・、別にファンでは無・・・(略))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
他の方々の発表は興味深いものが多くで、とても面白かったです。&lt;br /&gt;
自分もPyPIにあげられるようなライブラリ作れるようになりたいなぁと思いました。 &lt;br /&gt;
次回も時間が会えばぜひ参加したいです。&lt;br /&gt;
&lt;br /&gt;
主催者の皆様ありがとうございました。&lt;br /&gt;
&lt;br /&gt;
(追記)&lt;br /&gt;
調べたら、moriyoshiさんがpyakb48というモジュールをPyPIにあげていたようです。&lt;br /&gt;
中身みたのですが、かなりちゃんとつくられていました(doctestとかもある)。&lt;br /&gt;
私のは超劣化コピーですね。勉強して出なおしてきます。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/6289352544954614791/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/10/12python-mini-hack-thon.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6289352544954614791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6289352544954614791'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/10/12python-mini-hack-thon.html' title='第12回Python mini Hack-a-thon参加報告'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-2111674566617069535</id><published>2011-08-24T23:25:00.001+09:00</published><updated>2011-10-30T23:46:45.833+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="オーバーロード"/><title type='text'>Pythonで演算子オーバーロード</title><content type='html'>今更ながらPythonの演算子オーバーロード について調べたのでメモ。&lt;br /&gt;
クラスのメソッドを作成するだけなので 簡単にできますね。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;class OverLoadTest(object):
    def __init__(self, a):
        self.a = a

    # +
    def __add__(self, b):
        self.a = self.a + b
    # -
    def __sub__(self, b):
        self.a = self.a - b
    # /
    def __div__(self, b):
        self.a = self.a / b
    # *
    def __mul__(self, b):
        self.a = self.a * b

    def __repr__(self):
        return str(self.a)

if __name__ == &quot;__main__&quot;:
    o = OverLoadTest(5)
    print o
    o + 5
    print o
    o - 5
    print o
    o / 5
    print o
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
普段はJavaで書いているから演算子オーバーロードが頭にないなー。&lt;br /&gt;
&lt;br /&gt;
使ってるライブラリでも演算子オーバーロード見たことない気がする。 &lt;br /&gt;
(知らないだけか?)&lt;br /&gt;
効果的に使えるようになりたいですね。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/2111674566617069535/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/08/python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2111674566617069535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2111674566617069535'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/08/python.html' title='Pythonで演算子オーバーロード'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-1353796501672033952</id><published>2011-08-07T22:40:00.000+09:00</published><updated>2011-08-07T22:40:45.534+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="flask"/><category scheme="http://www.blogger.com/atom/ns#" term="streaming"/><title type='text'>FlaskでStreaming</title><content type='html'>久々にFlaskドキュメントページ見てたら、&lt;br /&gt;
Streamingのsnipetが掲載されてました。&lt;br /&gt;
(もしかして結構前から？)&lt;br /&gt;
&lt;br /&gt;
Werkzeugには0.5から機能としてはあるみたいなんで、&lt;br /&gt;
きっと昔からできたんでしょう。&lt;br /&gt;
&lt;br /&gt;
なかなか使い道ないけどTwitterのようなStreamingAPIとかかっこ良いですよね。&lt;br /&gt;
&lt;br /&gt;
つーことでコード。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;from flask import Flask
from flask import Response
import time

app = Flask(__file__)

@app.route(&quot;/streaming&quot;)
def streaming():
&amp;nbsp;&amp;nbsp;&amp;nbsp; def generate():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while True:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; time.sleep(1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield &quot;test\n&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return Response(generate(),direct_passthrough=True,mimetype=&#39;text/plain&#39;)

if __name__ == &quot;__main__&quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp; app.run()
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
ResponseにStreamingするためのジェネレータを渡すだけ。&lt;br /&gt;
direct_passthroughはジェネレータを変更させないための引数らしい、wrapして返すため、後で変更されても影響を受けないようになると思われる(WSGIの仕様っぽい)。&lt;br /&gt;
mime/typeはお好きなものを。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
それにしても簡単だなー。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/1353796501672033952/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/08/flaskstreaming.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/1353796501672033952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/1353796501672033952'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/08/flaskstreaming.html' title='FlaskでStreaming'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-7190258292318732334</id><published>2011-07-02T08:02:00.002+09:00</published><updated>2011-07-02T21:39:35.269+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="tips"/><category scheme="http://www.blogger.com/atom/ns#" term="unittest"/><title type='text'>Pythonで動的にサブクラスを生成</title><content type='html'>excelとかDBとかにテストケース用のデータを追加したら&lt;br /&gt;
勝手にテストクラスにテストケース(つまりテストメソッド)が追加される、&lt;br /&gt;
とかそういうことをやりたい。&lt;br /&gt;
&lt;br /&gt;
で、unittest.TestCaseクラスのサブクラスを&lt;br /&gt;
テストデータから動的に生成して実行したいと思ったときに、&lt;br /&gt;
どうやれば良いのかちょっと悩んだので、メモ。&lt;br /&gt;
&lt;br /&gt;
動的にサブクラスを生成するのは、&lt;br /&gt;
非常に単純でtype関数を使えばできる。&lt;br /&gt;
type関数は[クラス名]、[親クラスのタプル(多重継承も可)]、[付与したい属性の辞書]で&lt;br /&gt;
動的にクラス生成をできる。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;import unittest

def create_testmethod():
&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; テストメソッドを動的に生成
&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; def testMethod(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.assertEquals(1,1)
&amp;nbsp;&amp;nbsp;&amp;nbsp; return testMethod

def create_testclass():
&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TestCaseのサブクラスを動的に生成
&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; test_class = type(&#39;TestA&#39;, (unittest.TestCase,), {})
&amp;nbsp;&amp;nbsp;&amp;nbsp; setattr(test_class,&#39;testMethod&#39;,create_testmethod())
&amp;nbsp;&amp;nbsp;&amp;nbsp; return test_class

def suite():
&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; テストスイートを生成
&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; suite = unittest.TestSuite()
&amp;nbsp;&amp;nbsp;&amp;nbsp; test_class = create_testclass()
&amp;nbsp;&amp;nbsp;&amp;nbsp; suite.addTest(unittest.makeSuite(test_class))
&amp;nbsp;&amp;nbsp;&amp;nbsp; return suite

if __name__ == &quot;__main__&quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp; unittest.TextTestRunner().run(suite())
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
動的にテストクラス(unittest.TestCaseのサブクラス)を生成して、&lt;br /&gt;
動的にテストメソッドを追加することができる。&lt;br /&gt;
これを応用すればソースコード書かずにテストクラス、テストメソッドを動的に追加するようなプログラムができる。 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;FluJE_quick_lookup&quot; style=&quot;opacity: 0;&quot;&gt;Quick Lookup:&lt;input id=&quot;FluJE_quick_lookup_input&quot; /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/7190258292318732334/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/07/python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/7190258292318732334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/7190258292318732334'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/07/python.html' title='Pythonで動的にサブクラスを生成'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-679256524766931383</id><published>2011-05-27T00:19:00.001+09:00</published><updated>2011-05-27T00:25:37.868+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="flask"/><category scheme="http://www.blogger.com/atom/ns#" term="flask-extensions"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>DebugToolbarをFlaskにも</title><content type='html'>Flaskいいよー。Flask。&lt;br /&gt;
extensionsもガンガン増えてかなり色々なことができるようになりました。&lt;br /&gt;
&lt;br /&gt;
今日のネタはDebugToolbarです。&lt;br /&gt;
ちょっとハマったりしたのでそのメモがわりに。&lt;br /&gt;
DebugToolbarはDjangoのextensionでもあるものらしく、&lt;br /&gt;
レスポンスタイムとかログとかHttpHeaderとか見れるすぐれもの。&lt;br /&gt;
&lt;br /&gt;
Flaskでも使えるとなれば(Djangoでは使ったこと無いけど)これは試してみるしか&lt;br /&gt;
&lt;br /&gt;
いつものようにeasy_install なり pipなりでflask-debugtoolbarをインストールしたらええやないか。&lt;br /&gt;
&lt;br /&gt;
実行する最小セットは下記の通り。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;from flask import Flask
#DebugToolbarをインポート
from flaskext.debugtoolbar import DebugToolbarExtension

app = Flask(__name__)
#パネルを登録
app.config[&#39;DEBUG_TB_PANELS&#39;] = (
&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;flaskext.debugtoolbar.panels.headers.HeaderDebugPanel&#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;flaskext.debugtoolbar.panels.logger.LoggingPanel&#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;flaskext.debugtoolbar.panels.timer.TimerDebugPanel&#39;,
)
#Debug用のシークレットキーを追加、デバッグモードON
app.config[&#39;SECRET_KEY&#39;] = &#39;asd&#39;
app.config[&#39;DEBUG&#39;] = True

toolbar = DebugToolbarExtension(app)

@app.route(&#39;/&#39;)
def test():
&amp;nbsp;&amp;nbsp;&amp;nbsp; app.logger.info(&quot;hello&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp; return &quot;&quot;

if __name__ == &quot;__main__&quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp; app.run()&lt;/pre&gt;&lt;br /&gt;
これでローカルホストからは右にデバッグ用の怪しいボタンが出てくるので、&lt;br /&gt;
押すと色々なデバッグ情報が見れるようになる。&lt;br /&gt;
自分の環境ではflaskがurl_ruleっていう関数がねーみたいなエラーがでたので、&lt;br /&gt;
flaskを最新版(0.7)に換えたらOKでした。&lt;br /&gt;
&lt;br /&gt;
こういうのが増えてくると開発しやすくなりますねー。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/679256524766931383/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/05/debugtoolbarflask.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/679256524766931383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/679256524766931383'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/05/debugtoolbarflask.html' title='DebugToolbarをFlaskにも'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-8652099663344770231</id><published>2011-05-22T21:55:00.000+09:00</published><updated>2011-05-22T21:55:40.758+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="algorithm"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>挿入ソート</title><content type='html'>アルゴリズムクイックリファレンス買いました。&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2HaGyQ2Q9YUdzwmfG2iBxiAQfF5B0Jo7HjJMv7XDckNn9IZqRyNRSuMYngQjoWag5Oojdnts-bNaGY3lpmkvQ_ZVvoomb9sI2s_FeGJB-fFmjcEXcsjMyqb5jjEuYLsOsVg-9ecTU0Dmp/s1600/algorithm.jpg&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; width=&quot;141&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2HaGyQ2Q9YUdzwmfG2iBxiAQfF5B0Jo7HjJMv7XDckNn9IZqRyNRSuMYngQjoWag5Oojdnts-bNaGY3lpmkvQ_ZVvoomb9sI2s_FeGJB-fFmjcEXcsjMyqb5jjEuYLsOsVg-9ecTU0Dmp/s200/algorithm.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
購入動機は、&lt;br /&gt;
・アルゴリズムは大学生以来(しかも1-2年の時)やってないのでかなり鈍っている&lt;br /&gt;
・グラフ系のアルゴリズムとか学生時代にほとんどやってない&lt;br /&gt;
・プログラミングコンテストの予選を突破できるようになりたいので正しいアルゴリズムをきちんと学びたい(正しいアルゴリズムを選べるようになる、計算量を意識できるようになる)&lt;br /&gt;
です。&lt;br /&gt;
&lt;br /&gt;
つーことで早速挿入ソート&lt;br /&gt;
(多少Pythonicに直した…つもり)&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;

def sort(a):
    for i, e in enumerate(a):
        insert(a, i, a[i])


def insert(a, pos, value):
    i = pos - 1
    while i &gt;= 0 and a[i] &gt; value:
        a[i + 1] = a[i]
        i = i - 1
    a[i + 1] = value


if __name__ == &#39;__main__&#39;:
    data = [6, 3, 2, 1, 5, 4]
    sort(data)
    print data


&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;オーダー&lt;/b&gt;&lt;br /&gt;
最良 O(n)&lt;br /&gt;
平均 O(n^2)&lt;br /&gt;
最悪 O(n^2)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;挿入ソート特徴&lt;/b&gt;&lt;br /&gt;
要素数が少ない、最初からほぼ整列しているデータに対して有効&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;感想&lt;/b&gt;&lt;br /&gt;
かなり男らしい実装だが、&lt;br /&gt;
ほぼソートされている場合insert関数のwhileが小さくなるため、&lt;br /&gt;
結構高速に動作するらしい。&lt;br /&gt;
&lt;br /&gt;
がんばって一冊みっちり勉強したいとこです。(意気込み)</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/8652099663344770231/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/05/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8652099663344770231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8652099663344770231'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/05/blog-post.html' title='挿入ソート'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2HaGyQ2Q9YUdzwmfG2iBxiAQfF5B0Jo7HjJMv7XDckNn9IZqRyNRSuMYngQjoWag5Oojdnts-bNaGY3lpmkvQ_ZVvoomb9sI2s_FeGJB-fFmjcEXcsjMyqb5jjEuYLsOsVg-9ecTU0Dmp/s72-c/algorithm.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-6684695253822010267</id><published>2011-05-03T00:16:00.000+09:00</published><updated>2011-05-03T00:16:10.031+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pep8"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Pythonの命名規則のおさらいじゃい</title><content type='html'>どうもこんにちわ。&lt;br /&gt;
&lt;br /&gt;
いきなりですけどPythonのみでコーディングしている人は少ないのではないでしょうか。&lt;br /&gt;
私もJavaとPythonとjavascriptなどの複数の言語を業務で扱うことがあり、&lt;br /&gt;
ある程度慣れては来ていますが、命名規則がごっちゃになったりします。&lt;br /&gt;
&lt;br /&gt;
つーことで今更ながらPythonの超基本命名規則(by PEP8)のおさらい。&lt;br /&gt;
&lt;br /&gt;
&lt;table border=&quot;1&quot;&gt;&lt;tr&gt;&lt;td&gt;名称&lt;/td&gt;&lt;td&gt;規約&lt;/td&gt;&lt;td&gt;例&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;module名&lt;/td&gt;&lt;td&gt;lowercase&lt;/td&gt;&lt;td&gt;hamegg.py&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;class名&lt;/td&gt;&lt;td&gt;CapWords&lt;/td&gt;&lt;td&gt;class HamEgg(object):…&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;exception名&lt;/td&gt;&lt;td&gt;CapWords&lt;/td&gt;&lt;td&gt;class HamEggException(Exception):…&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;関数名&lt;/td&gt;&lt;td&gt;lowercase_with_underscores&lt;/td&gt;&lt;td&gt;def ham_egg():…&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;関数名(既存の文脈※)&lt;/td&gt;&lt;td&gt;mixedCase&lt;/td&gt;&lt;td&gt;def hamEgg():…&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;メソッド名&lt;/td&gt;&lt;td&gt;lowercase_with_underscores&lt;/td&gt;&lt;td&gt;def ham_egg(self):…&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;インスタンス変数名&lt;/td&gt;&lt;td&gt;lowercase_with_underscores&lt;/td&gt;&lt;td&gt;self.ham_egg = None&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;定数&lt;/td&gt;&lt;td&gt;UPPER_CASE_WITH_UNDERSCORES&lt;/td&gt;&lt;td&gt;HAM_EGG = &quot;ham_egg&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;
見返して思ったのはモジュール名にアンダースコアつけてるかも。恥ずかし。&lt;br /&gt;
&lt;br /&gt;
※たまにあるビルトイン系の関数名がmixedCaseになっていると混乱する元になりますね。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/6684695253822010267/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/05/python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6684695253822010267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6684695253822010267'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/05/python.html' title='Pythonの命名規則のおさらいじゃい'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-2822129282428063071</id><published>2011-03-15T21:55:00.000+09:00</published><updated>2011-03-15T21:55:44.357+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="flask"/><category scheme="http://www.blogger.com/atom/ns#" term="flask-extensions"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Flask-Script</title><content type='html'>みなさんFlaskしてますか。&lt;br /&gt;
Flask相変わらず良いですね。&lt;br /&gt;
extensionの数も順調に増えていて良いですね。&lt;br /&gt;
mongoだのcouchだのの単語がみえてnosqlもバッチリですね。&lt;br /&gt;
&lt;br /&gt;
ところでdjangoのmanage.py便利ですよね。&lt;br /&gt;
Flaskでもrunserverとかshellとかやりたい。&lt;br /&gt;
そんな時にはflask extensionsにあるFlask-Scriptですよ。&lt;br /&gt;
&lt;br /&gt;
インストールはいつもの通り&lt;br /&gt;
easy_installなりpipなりでflask-scriptとしてください。&lt;br /&gt;
&lt;br /&gt;
Webアプリ側はこんな感じ(applicaiton.py)&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#web application
from flask import Flask
from flask import jsonify

app = Flask(__name__)

@app.route(&#39;/spam&#39;)
def spam():
    return jsonify(res=&#39;ok&#39;)

if __name__ == &quot;__main__&quot;:
    app.run()
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
んでflask-script側。(manage.py)&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#script
from flaskext.script import Manager
from application import app 
manager = Manager(app)

#manage.py にhelloコマンドの追加
@manager.command
def hello():
    print &#39;hello&#39;

if __name__ == &quot;__main__&quot;:
    manager.run()
&lt;/pre&gt;&lt;br /&gt;
managerにアプリ登録してやるだけです。&lt;br /&gt;
&lt;br /&gt;
あとは&lt;br /&gt;
$python manage.py runserver&lt;br /&gt;
でサーバ起動とかできます。&lt;br /&gt;
$python manage.py shell&lt;br /&gt;
でインタラクティブシェル起動できます。&lt;br /&gt;
&lt;br /&gt;
@manager.commandで独自コマンドも簡単に追加できるので重宝しそうです。&lt;br /&gt;
&lt;br /&gt;
optionパーサも組み込まれているみたいなので、&lt;br /&gt;
applicationの起動に色々処理を追加したい場合などは使ってみると良いと思います。&lt;br /&gt;
&lt;br /&gt;
詳細はこちらです。&lt;br /&gt;
&lt;a href=&quot;http://packages.python.org/Flask-Script/&quot;&gt;http://packages.python.org/Flask-Script/&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/2822129282428063071/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/03/flask-script.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2822129282428063071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2822129282428063071'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/03/flask-script.html' title='Flask-Script'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-6621133664072725632</id><published>2011-02-13T17:47:00.000+09:00</published><updated>2011-02-13T17:47:53.535+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="whoosh"/><category scheme="http://www.blogger.com/atom/ns#" term="全文検索"/><title type='text'>Whooshでの横断検索とか</title><content type='html'>Whooshの機能についての調査をある程度備忘録的に記載しておく。&lt;br /&gt;
&lt;br /&gt;
まずUNIQUEなフィールドについて&lt;br /&gt;
Schema定義の際にフィールドのインスタンスにunique=Trueを渡すことで、&lt;br /&gt;
同じ値が入った時に上書きがされるようだ。&lt;br /&gt;
&lt;br /&gt;
Solrなどで使われる複数のフィールドを横断して検索できる&lt;br /&gt;
DisMax系のモジュールがWhooshでも存在し、結構簡単に使える。&lt;br /&gt;
&lt;br /&gt;
今回の検証スクリプトは下記&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;# -*- coding: utf-8 -*-
import sys 
from whoosh.index import create_in
from whoosh.fields import *
from whoosh.scoring import *
from whoosh.query import *
from whoosh.qparser import DisMaxParser

#idフィールドをユニークキーとする
schema = Schema(id=ID(stored=True,unique=True),
                name=NGRAM(stored=True),
                ruby=NGRAM(stored=True),
                address=NGRAM(stored=True),
                telephone=TEXT(stored=True))

ix = create_in(&quot;indexdir&quot;, schema)
writer = ix.writer()
writer.add_document(id=u&quot;001&quot;,
                    name=u&quot;コンビニA&quot;,
                    ruby=u&quot;こんびにえー&quot;,
                    address=u&quot;東京都&quot;,
                    telephone=u&quot;0312345678&quot;)
writer.add_document(id=u&quot;002&quot;,
                    name=u&quot;コンビニB&quot;,
                    ruby=u&quot;こんびにびー&quot;,
                    address=u&quot;千葉県&quot;,
                    telephone=u&quot;0471234567&quot;)
writer.commit()
from whoosh.qparser import QueryParser
searcher = ix.searcher()
q = sys.argv[1].decode(&#39;utf-8&#39;)
#nameとrubyとaddressとtelephoneフィールドを横断検索
parser = DisMaxParser({&quot;name&quot;:0.5,&quot;ruby&quot;: 0.5,&quot;address&quot;: 0.2,&quot;telephone&quot;: 0.1},schema)
query = parser.parse(q)

results = searcher.search(query)
for result in results:
    print result
&lt;/pre&gt;&lt;br /&gt;
ちょっとずつWhooshに慣れてきた。&lt;br /&gt;
かなりLuceneに近い使われ方を想定している模様。&lt;br /&gt;
Luceneを使っている人であれば結構簡単に使えるのでは。&lt;br /&gt;
&lt;br /&gt;
形態素系のAnalyzerがないので、きついところもあるかもしれないが、&lt;br /&gt;
結構Pluggableに作られているようだし、&lt;br /&gt;
MecabなどのAnalyzerも簡単に作れるかも。&lt;br /&gt;
次はそこら辺を調べる予定。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/6621133664072725632/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/02/whoosh.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6621133664072725632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6621133664072725632'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/02/whoosh.html' title='Whooshでの横断検索とか'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-6925566768077672983</id><published>2011-02-12T17:27:00.000+09:00</published><updated>2011-02-12T17:27:37.644+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="whoosh"/><category scheme="http://www.blogger.com/atom/ns#" term="全文検索"/><title type='text'>Whoosh Fields</title><content type='html'>Whooshのフィールドの種類の種類は以下。&lt;br /&gt;
やっぱりフィールドの種類はluceneに比べるとすごく少ない。&lt;br /&gt;
普通の日本語のフィールドだとngram一択かな。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.ID&lt;/b&gt;&lt;br /&gt;
シンプルな単一フィールド。&lt;br /&gt;
urlやファイルパス、カテゴリなどで使うと良いとのこと。&lt;br /&gt;
luceneやsolr経験者だとユニークキーのことかと思うかもしれないが、&lt;br /&gt;
この値が同じだと同じドキュメントになるわけではないので注意。&lt;br /&gt;
(同一のidのものを追加しても前のドキュメントは上書かれない)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.STORED&lt;/b&gt;&lt;br /&gt;
ストアするがインデックス化はしないフィールド。&lt;br /&gt;
検索には引っかからないようにしたいデータを入れる。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.KEYWORD&lt;/b&gt;&lt;br /&gt;
スペースやカンマで区切られている文字列をindex化するフィールド。&lt;br /&gt;
one two,threefourというデータであればone,two,threefourという3つのデータがインデックス化される。&lt;br /&gt;
フレーズ検索(続いた文字列群で検索)には対応していない。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.TEXT&lt;/b&gt;&lt;br /&gt;
タームポジション(文字列出現箇所)を記憶しているフィールド。&lt;br /&gt;
フレーズ検索に対応。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.NUMERIC&lt;/b&gt;&lt;br /&gt;
数値フィールド。&lt;br /&gt;
intおよびfloatの値に対応。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.BOOLEAN&lt;/b&gt;&lt;br /&gt;
booleanフィールド。&lt;br /&gt;
TrueかFalseのみ。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.DATETIME&lt;/b&gt;&lt;br /&gt;
日時フィールド。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;whoosh.fields.NGRAM and whoosh.fields.NGRAMWORDS&lt;/b&gt;&lt;br /&gt;
ngramフィールドとngramwordフィールド。&lt;br /&gt;
ngramフィールドは文字列をn文字で分割してindex化。&lt;br /&gt;
2gramだと[test] -&gt; [te] [es] [st]の3つのデータに分割される。&lt;br /&gt;
&lt;br /&gt;
ngramwordフィールドはキーワードをn単位で分割してindex化。&lt;br /&gt;
2gramだと[one two three] -&gt; [one two][two three]の2つのデータに分割される。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/6925566768077672983/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/02/whoosh-fields.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6925566768077672983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6925566768077672983'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/02/whoosh-fields.html' title='Whoosh Fields'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-8549866196777760452</id><published>2011-02-12T14:00:00.000+09:00</published><updated>2011-02-12T14:00:22.767+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="whoosh"/><category scheme="http://www.blogger.com/atom/ns#" term="全文検索"/><title type='text'>Whoosh Quick start</title><content type='html'>WhooshのQuickStartを試す。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;from whoosh.index import create_in
from whoosh.fields import *

#スキーマの作成(フィールドはtitleとpathとcontentの3つ)
#stored=Trueのものはインデックスにオリジナルデータを持たせ、検索時に結果として返す。
#stored=False(デフォルトはFalse)のものはindex化されるので全文検索は可能だがオリジナルデータは検索時にはわからなくなっている。
schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT)

#作成したスキーマのインデックスディレクトリ(indexdir)を作成
ix = create_in(&quot;indexdir&quot;, schema)
#indexwriterを作成
writer = ix.writer()

#ドキュメントをインデックスに追加
writer.add_document(title=u&quot;First document&quot;, path=u&quot;/a&quot;,
                    content=u&quot;This is the first document we&#39;ve added!&quot;)
writer.add_document(title=u&quot;Second document&quot;, path=u&quot;/b&quot;,
                    content=u&quot;The second one is even more interesting!&quot;)
#コミットの実行 indexファイルへの書き込み
writer.commit()


from whoosh.qparser import QueryParser
#indexsearcherを作成
searcher = ix.searcher()
#検索クエリの作成(contentにfirstを含むドキュメント)
query = QueryParser(&quot;content&quot;,schema = ix.schema).parse(u&quot;first&quot;)
#検索の実行
results = searcher.search(query)
print results[0]
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;実行結果&lt;/b&gt;&lt;br /&gt;
Hit {&#39;path&#39;: u&#39;/a&#39;, &#39;title&#39;: u&#39;First document&#39;}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
とりあえず使い始めは簡単。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/8549866196777760452/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/02/whoosh-quick-start.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8549866196777760452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8549866196777760452'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/02/whoosh-quick-start.html' title='Whoosh Quick start'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-5372499012184431768</id><published>2011-02-12T13:43:00.000+09:00</published><updated>2011-02-12T13:43:20.776+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pylucene"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="whoosh"/><category scheme="http://www.blogger.com/atom/ns#" term="全文検索"/><title type='text'>Python上での全文検索</title><content type='html'>Pythonで全文検索したくて少し調べた。&lt;br /&gt;
&lt;br /&gt;
pyluceneとWhooshというのがあるらしい。&lt;br /&gt;
&lt;br /&gt;
pyluceneはJavaで作られた全文検索エンジンのluceneの&lt;br /&gt;
pythonバインディング版。&lt;br /&gt;
jccというpythonからJavaを呼び出すためのライブラリを利用している。&lt;br /&gt;
(jccはpyluceneのために作られた模様)&lt;br /&gt;
なので実処理はJavaで行われている。&lt;br /&gt;
&lt;br /&gt;
Whooshは後発でpurepythonで書かれている。&lt;br /&gt;
LuceneのAPIに似せたAPIでLuceneを知っている人であれば割ととっつきやすいのかも。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
どっちも少し触ってみた感想は、&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;pylucene&lt;/b&gt;&lt;br /&gt;
長所&lt;br /&gt;
・Luceneを知っていればAPI同じで学習のオーバーヘッドが少ない。&lt;br /&gt;
・Luceneからも読める。つまりJavaとインデックスを共有できる。(試してないけど当然Solrからも使えるはず)&lt;br /&gt;
短所&lt;br /&gt;
・インストール面倒。(特にJCC)&lt;br /&gt;
・起動処理が遅い。(JCCのinitVMでJavaVMの起動に時間がかかっている印象)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Whoosh&lt;/b&gt;&lt;br /&gt;
長所&lt;br /&gt;
・インストール簡単・&lt;br /&gt;
・使い方も結構分かりやすい。&lt;br /&gt;
短所&lt;br /&gt;
・日本語の機能的にLuceneより劣る(日本語用のAnalyzerが不足している)&lt;br /&gt;
不明&lt;br /&gt;
・速度的にLuceneより遅い?(検索/インデックス作成が静的型付け言語で行われるか、スクリプト言語で行われるかの差)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lucene経験者としてはpyluceneがいい感じだが、&lt;br /&gt;
Whooshもかなりいい感じなので期待したいところ。&lt;br /&gt;
&lt;br /&gt;
しばらくはWhooshを評価がてら使ってみることにする。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/5372499012184431768/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/02/python.html#comment-form' title='4 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/5372499012184431768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/5372499012184431768'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/02/python.html' title='Python上での全文検索'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-2770813655431870381</id><published>2011-01-22T12:06:00.002+09:00</published><updated>2011-01-22T12:09:04.081+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="appengine"/><category scheme="http://www.blogger.com/atom/ns#" term="flask"/><category scheme="http://www.blogger.com/atom/ns#" term="gae"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>GAE上のFlaskで画像アップ&amp;表示</title><content type='html'>みなさん。Flask使ってますか。&lt;br /&gt;
&lt;br /&gt;
Flask最高ですね。&lt;br /&gt;
最近はWebアプリ作るときは何やるにしてもFlaskでやってます。&lt;br /&gt;
Javaのモジュールが必要なときはJythonつかってFlask動かすくらいです。&lt;br /&gt;
(これはまた別の話)&lt;br /&gt;
&lt;br /&gt;
GAEも最高ですね。&lt;br /&gt;
ということで、Flask,GAEについて今日は書きたいと思います。&lt;br /&gt;
まあGAE上でFlask使う方法は色々なところで書かれているので割愛。&lt;br /&gt;
&lt;br /&gt;
今日はGAE上のFlaskで画像のアップロードと表示について&lt;br /&gt;
結構時間かかったので備忘録として書きます。&lt;br /&gt;
&lt;br /&gt;
pythonコードは以下のような感じ。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;from flask import Flask
from flask import request
from flask import Response
from google.appengine.ext import db

app = Flask(__name__)

@app.route(&#39;/image/upload&#39;,methods=[&#39;POST&#39;])
def upload_image():
    &quot;&quot;&quot;画像アップロード&quot;&quot;&quot;
    uploaded_image = request.files[&#39;image&#39;]
    image = Image()
    image.content_type = uploaded_image.content_type
    image.image = uploaded_image.stream.read()
    image.put()
    return &#39;ok&#39;

@app.route(&#39;/image&#39;)
def disp():
    &quot;&quot;&quot;keyで表示&quot;&quot;&quot;
    image = Image.get(request.args.get(&#39;key&#39;,&#39;&#39;))
    return Response(response=image.image,content_type=image.content_type)

class Image(db.Model):
    &quot;&quot;&quot;画像保存用エンティティ&quot;&quot;&quot;
    content_type= db.StringProperty()
    image = db.BlobProperty()
&lt;/pre&gt;&lt;br /&gt;
まず登録時にはBigtable側に画像のバイナリとコンテントタイプを保存しておく。&lt;br /&gt;
で表示側にはResponseに画像バイナリとコンテントタイプを返してやる。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
画像アップロードのformはこんな感じ&lt;br /&gt;
&lt;br /&gt;
&amp;lt;form action=&amp;quot;/admin/image/upload&amp;quot; enctype=&amp;quot;multipart/form-data&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;input type=&amp;quot;file&amp;quot; name=&amp;quot;image&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;upload&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
表示側はこんな感じ&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img src=&amp;quot;/image?key={{画像のキー}}&amp;quot; &amp;gt;</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/2770813655431870381/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/01/gaeflask.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2770813655431870381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2770813655431870381'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/01/gaeflask.html' title='GAE上のFlaskで画像アップ&amp;表示'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-6516159765921739097</id><published>2011-01-08T19:30:00.002+09:00</published><updated>2011-01-08T22:51:06.657+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="zen"/><title type='text'>The Zen of Python</title><content type='html'>Pythonのインタラクティブシェルでthisをimportすると&lt;br /&gt;The Zen of Pythonを読むことができる。&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;br /&gt;&gt;&gt;&gt; import this&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;英語のリハビリとして辞書片手に翻訳してみる。&lt;br /&gt;&lt;br /&gt;-翻訳-&lt;br /&gt;醜いよりも美しいほうがいい&lt;br /&gt;わかりにくいよりも分りやすいほうがいい&lt;br /&gt;複雑よりもシンプルなほうがいい&lt;br /&gt;入り組んでいるよりも複合のほうがいい&lt;br /&gt;ネストしているよりもフラットなほうがいい&lt;br /&gt;密度は低いほうがいい&lt;br /&gt;読みやすさが重要&lt;br /&gt;特別な場合でも規則を破るほど特別ではない&lt;br /&gt;けれども実用性は純粋性をしのぐ&lt;br /&gt;明確に沈黙させているので無い限り、決してエラーを黙って通してはいけない&lt;br /&gt;曖昧さに直面したとき、推測するという誘惑に負けてはいけない&lt;br /&gt;明らかな方法がひとつ、なるべくひとつだけあるべき&lt;br /&gt;たとえオランダ人以外には明らかでなかったとしても&lt;br /&gt;何もしないよりは今やる方がいい&lt;br /&gt;けれども今すぐにやらないほうがいいこともたびたびある&lt;br /&gt;説明が大変な実装であるならば、それは良くないアイディア&lt;br /&gt;説明が簡単な実装であるならば、それがきっと良いアイディア&lt;br /&gt;名前空間こそが良いアイディア、これらをどんどんやっていこう&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;-原文-&lt;br /&gt;Beautiful is better than ugly.&lt;br /&gt;Explicit is better than implicit.&lt;br /&gt;Simple is better than complex.&lt;br /&gt;Complex is better than complicated.&lt;br /&gt;Flat is better than nested.&lt;br /&gt;Sparse is better than dense.&lt;br /&gt;Readability counts.&lt;br /&gt;Special cases aren&#39;t special enough to break the rules.&lt;br /&gt;Although practicality beats purity.&lt;br /&gt;Errors should never pass silently.&lt;br /&gt;Unless explicitly silenced.&lt;br /&gt;In the face of ambiguity, refuse the temptation to guess.&lt;br /&gt;There should be one-- and preferably only one --obvious way to do it.&lt;br /&gt;Although that way may not be obvious at first unless you&#39;re Dutch.&lt;br /&gt;Now is better than never.&lt;br /&gt;Although never is often better than *right* now.&lt;br /&gt;If the implementation is hard to explain, it&#39;s a bad idea.&lt;br /&gt;If the implementation is easy to explain, it may be a good idea.&lt;br /&gt;Namespaces are one honking great idea -- let&#39;s do more of those!</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/6516159765921739097/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/01/zen-of-python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6516159765921739097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6516159765921739097'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/01/zen-of-python.html' title='The Zen of Python'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-8827241423569715810</id><published>2011-01-08T13:36:00.005+09:00</published><updated>2011-01-08T14:12:41.651+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="flask"/><category scheme="http://www.blogger.com/atom/ns#" term="jsonp"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>FlaskでJSONP</title><content type='html'>PythonのマイクロフレームワークFlaskでは&lt;br /&gt;JSONを返却するためのメソッドjsonifyが定義されている。&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;br /&gt;from flask import Flask&lt;br /&gt;from flask import jsonify&lt;br /&gt;&lt;br /&gt;app=Flask(__name__)&lt;br /&gt;&lt;br /&gt;@app.route(&#39;/test.json&#39;)&lt;br /&gt;def test_json():&lt;br /&gt;    return jsonify(res=&#39;test&#39;)&lt;br /&gt;&lt;br /&gt;if __name__ == &#39;__main__&#39;:&lt;br /&gt;    app.run()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;/test.jsonでリクエストすると&lt;br /&gt;{&lt;br /&gt;  res:&#39;test&#39;&lt;br /&gt;}&lt;br /&gt;という結果が帰ってくる&lt;br /&gt;&lt;br /&gt;JSONPにしたい場合はjsonifyは使えない。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;br /&gt;@app.route(&#39;/test.jsonp&#39;)&lt;br /&gt;def test_jsonp():&lt;br /&gt;    import json&lt;br /&gt;    request.args.get(&#39;callback&#39;) + &#39;(&#39; + json.dumps(dict(res=&#39;test&#39;)) + &#39;)&#39;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;というように自分でリクエストパラメータからcallbackを受け取って&lt;br /&gt;付与して返す必要がある。&lt;br /&gt;&lt;br /&gt;ただしこのままでは、mimetypeの指定がないので&lt;br /&gt;厳密にはmimetypeの指定を行わなくてはならない。&lt;br /&gt;script/javascript&lt;br /&gt;&lt;br /&gt;現状FlaskのJSONP用のmethod(padded_jsonify)が要望として上がっているが、&lt;br /&gt;jsonifyのように*args,**kwdとすべての引数がjsonオブジェクトになるような機能のため&lt;br /&gt;callbackが入る余地が無いみたいで、提案が今は棄却されている模様。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/8827241423569715810/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2011/01/flaskjsonp.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8827241423569715810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8827241423569715810'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2011/01/flaskjsonp.html' title='FlaskでJSONP'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-2081404341497031893</id><published>2010-06-27T10:48:00.002+09:00</published><updated>2010-06-27T10:59:00.436+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="tips"/><title type='text'>PythonStartup</title><content type='html'>Pythonのコマンドラインでの開発の際に過去のコマンドヒストリや補完のやり方は以下のとおり。&lt;br /&gt;&lt;br /&gt;.pythonstartupファイルをhomeに作成し下記の内容にする。&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;br /&gt;# -*- coding: utf-8 -*-&lt;br /&gt;import readline&lt;br /&gt;import rlcompleter&lt;br /&gt;import atexit&lt;br /&gt;import os&lt;br /&gt;&lt;br /&gt;readline.parse_and_bind(&#39;Tab: complete&#39;)&lt;br /&gt;# osxの場合は下記でないと動かないかも&lt;br /&gt;#readline.parse_and_bind(&quot;bind ^I rl_complete&quot;)&lt;br /&gt;histfile = os.path.join(os.environ[&#39;HOME&#39;], &#39;.pythonhistory&#39;)&lt;br /&gt;try:&lt;br /&gt;    readline.read_history_file(histfile)&lt;br /&gt;except IOError:&lt;br /&gt;    pass&lt;br /&gt;atexit.register(readline.write_history_file,histfile)&lt;br /&gt;del os, histfile, readline, rlcompleter, atexit&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;で環境変数に以下を追加。&lt;br /&gt;PYTHONSTARTUP=~/.pythonstartup&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;これでコマンドラインでタブ補完と上下キーでヒストリが表示されるようになる。&lt;br /&gt;ipythonも素敵だけど、サーバでのインストールが面倒なときや、&lt;br /&gt;windowsではこっちの方が良いかも(windowsのipythonは表示がおかしなことになる。自分だけか)</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/2081404341497031893/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2010/06/pythonstartup.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2081404341497031893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2081404341497031893'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2010/06/pythonstartup.html' title='PythonStartup'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-6583830649078218690</id><published>2010-06-19T22:07:00.006+09:00</published><updated>2010-06-20T16:56:09.738+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="本"/><title type='text'>エキスパート　Python プログラミング</title><content type='html'>買いました。&lt;br /&gt;&lt;br /&gt;内容は、表紙の帯(と思ったら帯じゃない)に書いてある通り、Pythonプログラミングについてのベストプラクティスという題材で書いてあるので趣味プログラミングでしかPythonを使っていない私にとって非常にありがたい内容。&lt;br /&gt;&lt;br /&gt;業務でちょっとしたツール(スクリプト)を作る時に個人的にPythonを使っているが、一般的な書き方で他の人に展開しても恥ずかしくないようなコードを書いていこう。&lt;br /&gt;&lt;br /&gt;とりあえず、写経します。&lt;br /&gt;&lt;div style=&quot;opacity: 0;&quot; id=&quot;FluJE_quick_lookup&quot;&gt;&lt;span&gt;Quick Lookup:&lt;/span&gt;&lt;input id=&quot;FluJE_quick_lookup_input&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;bc1=FFFFFF&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=noisyobject-22&amp;o=9&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;asins=4048686291&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/6583830649078218690/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2010/06/python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6583830649078218690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/6583830649078218690'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2010/06/python.html' title='エキスパート　Python プログラミング'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-2878365715753525768</id><published>2010-05-30T19:01:00.003+09:00</published><updated>2010-06-20T16:57:56.424+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="o&#39;reilly"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><title type='text'>ハイパフォーマンスWebサイト</title><content type='html'>O&#39;REILLYから出ているハイパフォーマンスWebサイトを読んでいる。&lt;br /&gt;&lt;br /&gt;サイトを高速にする14個のルールが章ごとにわかりやすく書かれている。&lt;br /&gt;&lt;br /&gt;あんまりWebサイト構築したことないからかなり勉強になる。&lt;br /&gt;&lt;br /&gt;まず最初に結構びっくりする内容があったのでメモがてら書いておく。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;・レスポンスにかかっている時間のほとんどはフロントエンドでの処理である&lt;/b&gt;&lt;br /&gt;高速にするという作業は、DBのインデックスチューニングであったり、&lt;br /&gt;レスポンスのアルゴリズムといったことに考えがいきがち(少なくとも私は)だが、&lt;br /&gt;実際には8-9割がフロントエンドの処理に費やされている。&lt;br /&gt;つまりブラウザに表示する時間がかかっているということ。&lt;br /&gt;&lt;br /&gt;高速なサイトを実現するためには、ブラウザでの処理を高速化させることが重要だとおいうことらしい。&lt;br /&gt;&lt;br /&gt;読んで良かったところを抜粋しておく。&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1章 HTTPリクエストを減らす&lt;/b&gt;&lt;br /&gt;・イメージマップやCSSスプライトを利用して画像をまとめる&lt;br /&gt;・スクリプトやスタイルシートを結合する&lt;br /&gt;・ファイルをまとめてリクエスト数を減らす&lt;br /&gt;&lt;br /&gt;&gt;なるほどという感じ。&lt;br /&gt;とにかく1リクエストにかかるオーバーヘッドはかなりのものらしい。&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;3章 Expiresヘッダを設定する&lt;/b&gt;&lt;br /&gt;・クライアントにキャッシュさせるようにHTTPヘッダにExpiresを設定させる&lt;br /&gt;・ファイル名にバージョンをつけることで変更をブラウザに認識させる&lt;br /&gt;&lt;br /&gt;&gt;クライアントにキャッシュさせるっていうのは当たり前な気がしていたが、&lt;br /&gt;ファイル名にバージョンつけて変更を通知するっていのは賢い。&lt;br /&gt;たしかニコニコ動画がそうやってるって何かに書いてあった。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5章 スタイルシートは先頭に置く&lt;/b&gt;&lt;br /&gt;・最後に置くとスタイルシートが読み込まれるまで表示されない&lt;br /&gt;&lt;b&gt;6章 スクリプトは最後に置く&lt;/b&gt;&lt;br /&gt;・スクリプトが読み込まれている間はレンダリングが中断される&lt;br /&gt;&lt;br /&gt;&gt;外部ファイル関係。&lt;br /&gt;レンダリングが逐次実行されることで、見ている人のストレスが低くなるらしい。&lt;br /&gt;レンダリングが中断されないようにするためには&lt;br /&gt;スタイルシートは先頭にスクリプトは最後に置くのが吉とのこと&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Webやっている人には当たり前のTipsだったりするんですかね。&lt;br /&gt;あーWebやりたいす。&lt;br /&gt;&lt;br /&gt;&lt;iframe src=&quot;http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;bc1=FFFFFF&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=noisyobject-22&amp;o=9&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;asins=487311361X&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/2878365715753525768/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2010/05/web.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2878365715753525768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/2878365715753525768'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2010/05/web.html' title='ハイパフォーマンスWebサイト'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-8680427973718530185</id><published>2010-05-30T19:00:00.001+09:00</published><updated>2010-05-30T19:01:10.190+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="kestrel"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>kestrel</title><content type='html'>Twitterでも使われているMessageQueingシステムのkestrelの記事を読み、&lt;br /&gt;memcachedのプロトコルで使えるということだったのでちょっと使ってみた。&lt;br /&gt;&lt;br /&gt;バイナリが発見できなかったので、ソースからコンパイルすることにした。&lt;br /&gt;とりあえず以下からソースコードをダウンロード。&lt;br /&gt;&lt;a title=&quot;http://github.com/robey/kestrel/tree/master&quot; href=&quot;http://github.com/robey/kestrel/tree/master&quot; mce_href=&quot;http://github.com/robey/kestrel/tree/master&quot;&gt;http://github.com/robey/kestrel/tree/master&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;JavaなのででビルドはAnt。&lt;br /&gt;Windows上でビルドするとどうもうまくいかない。&lt;br /&gt;&lt;br /&gt;build.xmlを読むとどうやらOSXとLinuxでしかできないよう。&lt;br /&gt;build.xmlを書き換えるのも面倒だったので、VMWare上のDebianでビルド。&lt;br /&gt;今度は上手くいった。&lt;br /&gt;&lt;br /&gt;ジャーナリングしたりログの出力パスの設定があるので、&lt;br /&gt;Windows上で使うためには設定がいくつか必要。&lt;br /&gt;&lt;br /&gt;とりあえずさくっと使うためにはconfigディレクトリ内の&lt;br /&gt;production.confの以下の部分を変更&lt;br /&gt;&lt;br /&gt;-ログ設定-----------------------------------------------------&lt;br /&gt;log {&lt;br /&gt;  filename = &quot;/var/log/kestrel/kestrel.log&quot;　→任意のパスに変更&lt;br /&gt;  roll = &quot;daily&quot;&lt;br /&gt;  level = &quot;info&quot;&lt;br /&gt;}&lt;br /&gt;-ジャーナリング設定-------------------------------------------&lt;br /&gt;queue_path = &quot;/var/spool/kestrel&quot;　→任意のパスに変更&lt;br /&gt;--------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;ポートとかも設定ファイル上で変える模様。&lt;br /&gt;&lt;br /&gt;以下のコマンドで早速起動。&lt;br /&gt;java -jar kestrel-1.1.2.jar&lt;br /&gt;&lt;br /&gt;実際にpythonからアクセスしてみた。&lt;br /&gt;&lt;br /&gt;&lt;a title=&quot;以前書いたmemcachedのソースコード&quot; href=&quot;http://blog.livedoor.jp/noisyobject/archives/853762.html&quot; mce_href=&quot;http://blog.livedoor.jp/noisyobject/archives/853762.html&quot;&gt;以前書いたmemcachedのソースコード&lt;/a&gt;そのままで使える。&lt;br /&gt;&lt;br /&gt;違うのはアクセスが2回行われたときにエラーが発生する。&lt;br /&gt;まあキューなので当たり前だがちょっと感動。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/8680427973718530185/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2010/05/kestrel.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8680427973718530185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/8680427973718530185'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2010/05/kestrel.html' title='kestrel'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-5241594805223421645</id><published>2010-05-30T18:59:00.002+09:00</published><updated>2010-05-30T18:59:55.616+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="juno"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>juno</title><content type='html'>MOONGIFTに紹介されていたので&lt;br /&gt;PythonのWebFW junoを使ってみる。&lt;br /&gt;&lt;br /&gt;Rubyの軽量WebFWのSinatraに近いらしく&lt;br /&gt;かなり簡単にWebアプリがかけるということらしい。&lt;br /&gt;&lt;br /&gt;まずとりあえずインストール。&lt;br /&gt;&lt;br /&gt;以下のサイトからjuno本体をダウンロードする。&lt;br /&gt;&lt;br /&gt;http://brianreily.com/project/juno/&lt;br /&gt;&lt;br /&gt;本体を解凍したフォルダ内で以下のコマンド実行しインストール&lt;br /&gt;&lt;br /&gt;$python setup.py install&lt;br /&gt;&lt;br /&gt;すると色々インストールしておけと言われるので&lt;br /&gt;以下のコマンドでインストールしておく。&lt;br /&gt;&lt;br /&gt;$easy_install SQLAlchemy&lt;br /&gt;$easy_install Jinja2&lt;br /&gt;$easy_install Mako&lt;br /&gt;$easy_install Werkzeug&lt;br /&gt;&lt;br /&gt;さて実際のアプリケーションを書く&lt;br /&gt;&lt;br /&gt;junoのサンプルをとりあえず利用した。&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 204, 255);&quot; mce_style=&quot;color: #99ccff;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 255);&quot; mce_style=&quot;color: #0000ff;&quot;&gt;&lt;span style=&quot;background-color: rgb(255, 255, 255);&quot; mce_style=&quot;background-color: #ffffff;&quot;&gt;from juno import *&lt;br /&gt;&lt;br /&gt;@route(&#39;/&#39;)&lt;br /&gt;def index(web):&lt;br /&gt;    return &#39;Juno says Hi&#39;&lt;br /&gt;&lt;br /&gt;run()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;&lt;br /&gt;これを普通にPythonインタプリタで実行する。&lt;br /&gt;以下のようなログがコマンドプロンプトに表示される&lt;br /&gt;&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 0, 0);&quot; mce_style=&quot;color: #ff0000;&quot;&gt;running Juno development server, &lt;c-c&gt; to exit...&lt;br /&gt;connect to 127.0.0.1:8000 to use your app...&lt;br /&gt;&lt;br /&gt;GET request for /...&lt;br /&gt;/ matches, calling index()...&lt;/span&gt;&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;&lt;br /&gt;WEBブラウザ以下のアドレスにアクセスすると&lt;br /&gt;http://127.0.0.1:8000&lt;br /&gt;&lt;br /&gt;画面出た。&lt;br /&gt;&lt;br /&gt;本気ですごい。超簡単。</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/5241594805223421645/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2010/05/juno.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/5241594805223421645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/5241594805223421645'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2010/05/juno.html' title='juno'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1014022074285403080.post-899610440070385778</id><published>2010-05-30T18:56:00.000+09:00</published><updated>2010-05-30T18:58:23.958+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="memcached"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>memcached</title><content type='html'>memcachedを使ってみたかったので、せっかくなので、&lt;br /&gt;pythonでやってみた。&lt;br /&gt;&lt;br /&gt;memcachedのpython用クライアントインストールは&lt;br /&gt;easy_installを使った。&lt;br /&gt;&lt;br /&gt;easy_installをインストールした後で以下のコマンドを実行&lt;br /&gt;$easy_install python-memcached&lt;br /&gt;&lt;br /&gt;memcachedをインストールして起動した状態で以下のコードを実行&lt;br /&gt;&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;import memcache&lt;br /&gt;&lt;br /&gt;#memcached index key&lt;br /&gt;indexkey = 1000&lt;br /&gt;&lt;br /&gt;#set data to memcached&lt;br /&gt;#initialize memecached&lt;br /&gt;cachedata = &#39;cache data&#39;&lt;br /&gt;memcachedclient = memcache.Client([&#39;127.0.0.1:11211&#39;])&lt;br /&gt;memcachedclient.flush_all()&lt;br /&gt;memcachedclient.set(str(indexkey), cachedata)&lt;br /&gt;&lt;br /&gt;#get data from memcached&lt;br /&gt;memcachedclient = memcache.Client([&#39;127.0.0.1:11211&#39;])&lt;br /&gt;cacheddata = memcachedclient.get(str(indexkey))&lt;br /&gt;print cacheddata&lt;br /&gt;&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;&lt;br /&gt;動いた。使うのはめちゃくちゃ簡単。&lt;br /&gt;&lt;br /&gt;キーは文字列のみを受け付けるようだ。&lt;br /&gt;integerだとだめって以下のようなエラーが出た。&lt;br /&gt;(memcache.MemcachedKeyTypeError: Key must be str()&#39;s)</content><link rel='replies' type='application/atom+xml' href='http://noisyobject.blogspot.com/feeds/899610440070385778/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://noisyobject.blogspot.com/2010/05/memcached.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/899610440070385778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1014022074285403080/posts/default/899610440070385778'/><link rel='alternate' type='text/html' href='http://noisyobject.blogspot.com/2010/05/memcached.html' title='memcached'/><author><name>noisyobject</name><uri>http://www.blogger.com/profile/12105211107589487865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>