Home > Uncategorized > Twinado = Tornado + async-python-twitter

Twinado = Tornado + async-python-twitter

Twinadoという携帯向けのTwitterクライアントを書いてみました。日常的に使えるレベルにはなっていると思います。

特徴としては最近Facebookが公開したTornadoというフレームワークを使って、Twitter API呼び出しが全て非同期に行われている点です。なので、コネクション数が増えても高速に動くはずです。現状DoCoMo P905iでしか動作確認していません。

きっかけとしては、最近Perl界隈で非同期処理が流行っているのを見て、楽しそうだと思っていたところに、Tornadoが公開されたので、少し使ってみるかと思い立った事です。Tornadoについては以下を参考にして下さい(日本語訳、お疲れ様です!)。

Tornadoの特徴は、リクエストハンドラ内でHTTPリクエストを非同期に発行出来る事です。これによって、サーバー側でのネットワークの待ち時間を減らし、その間に別のリクエストを処理する事が出来ます。以下のサンプルコードは、FriendFeedのAPIを非同期で取得している例になります。取得終了時にon_response関数が呼ばれます。


class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        http = tornado.httpclient.AsyncHTTPClient()
        http.fetch("http://friendfeed-api.com/v2/feed/bret",
                   callback=self.async_callback(self.on_response))

    def on_response(self, response):
        if response.error: raise tornado.web.HTTPError(500)
        json = tornado.escape.json_decode(response.body)
        self.write("Fetched " + str(len(json["entries"])) + " entries "
                   "from the FriendFeed API")
        self.finish()

で、何か作ろうと思って、激しく外部APIアクセスするものって何かなと思ったところ、Twitterクライアントしか思いつかなかったので、作る事にしました。PythonのTwitterクライアントライブラリ「python-twitter」とTornadoに付属しているAsyncHTTPClientを密結合させました。

変更後のソースはgithubにおいてあります。今のところ、一部の関数のみ非同期呼び出しに対応しています。差分を見て頂くと分かりますが、_FetchUrlAsync関数が肝です。

APIの非同期呼び出しは以下のように書けます。GetUserコマンドに渡しているasync_callbackというのがポイントです。読み込みが終わった瞬間に引数で渡した関数を呼び出してくれます。on_response関数ではAPIで取得したUserクラスのインスタンスが渡って来ます。


class UserMainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self, username, password):
        try:
            api = async_twitter.Api(username, password)
            api.GetUser(user = username,
                        async_callback = self.async_callback(self.on_response))
        except:
            self.write("twitter api failed")
            print sys.exc_info()
            self.finish()

    def on_response(self, user):
        if user == None:
            self.write("twitter api failed")
            self.finish()
            return
        self.do_render(user)

    def do_render(self, user):
        self.render("tpl/user_main.html",
                    user = user)

この辺でかなり満足し切ったのですが、適当に機能を足して、冒頭で紹介したTwinadoという携帯向けのTwitterクライアントを書いてみました。

Tornadoで書いてみた雑感ですが、コールバックベースの非同期処理は記述が面倒臭すぎます。特にAPIを複数回呼びだしたりする必要の有る処理なんかは、コールバック関数をその都度作らないといけない。

また結果を引き回すために関数のcurry化をしたいのだけど、pythonだとfunctoolsというモジュールで明示的に関数を作ってやる必要が有ったり、楽とは言えない感じです。関数型言語だと大分マシにはなるけど、根本的解決じゃ無い気がします。

エラー処理も、結構問題です。メソッド内で起こったエラーをコールバック内に伝える必要があるため、必然的にオブジェクトを引き回す必要が有ります。

かと言って条件引数引き回すのもなんだかなぁ…。

Similar Posts:

Comments:2

okuji 09-09-23 (Wed) 14:32

Pythonならこういうのはcogenとかの方が楽だと思うんですけど。
http://code.google.com/p/cogen/

kiyoto 09-10-01 (Thu) 11:42

pythonネタだ。おれでもわかるw

Comment Form
Remember personal info

Trackbacks:3

Trackback URL for this entry
http://kzk9.net/blog/2009/09/twinado_is_tornado_plus_async-python-twitter.html/trackback
Listed below are links to weblogs that reference
Twinado = Tornado + async-python-twitter from moratorium
pingback from Tweets that mention Twinado = Tornado + async-python-twitter - moratorium -- Topsy.com 09-09-23 (Wed) 2:18

[...] This post was mentioned on Twitter by tnk. tnk said: Twinado = Tornado + async-python-twitter - moratorium http://bit.ly/3yIoQx [...]

pingback from Twinado = Tornado + async-python-twitter – moratorium « とっても! ちゅどん(雑記帳) 09-09-23 (Wed) 4:20

[...] Twinado = Tornado + async-python-twitter – moratorium Twinado = Tornado + async-python-twitter – moratorium [...]

pingback from Twinado 携帯向けTwitterクライアント | Twitterナビ 09-09-24 (Thu) 21:55

[...] 作者のkzk_moverさんによる解説記事はこちら Twinado = Tornado + async-python-twitter – moratorium [...]

Home > Uncategorized > Twinado = Tornado + async-python-twitter

お薦め本
広告
Archives
Categories

Return to page top