SimpleXMLRPCServer
SimpleXMLRPCServerを使ってみます。
- 引数で (アドレス, ポート) というタプルを与えてSimpleXMLRPCServerのインスタンスを作る
- register_instance、register_functionで公開するAPIをインスタンスに登録
- serve_foreverでlisten
基本的にはこれだけです。簡単ですね。
# server.py class Foo: def add(self, a, b): return a+b def get_list(self, *a): return [str(i)+'!' for i in a] def get_dict(self): return {'a': 'apple', 'b': 'banana', 'o': 'orange', } def hello(self): print 'hello' return True def sub(a, b): return a-b import SimpleXMLRPCServer SimpleXMLRPCServer.SimpleXMLRPCServer.allow_reuse_address=True s = SimpleXMLRPCServer.SimpleXMLRPCServer(('localhost', 12345)) s.register_instance(Foo()) s.register_function(sub) s.register_function(lambda x, y: x*y, 'mul') s.serve_forever()
# client.py import xmlrpclib s = xmlrpclib.ServerProxy('http://localhost:12345') print s.add(1, 2) print s.sub(10, 9) print s.mul(11, 11) print s.get_list(1, 2, 3, 4, 5, 6, 'foo', 'bar') print s.get_dict() s.hello()
実行結果は以下のようになります
> python server.py
> python client.py 3 1 121 ['1!', '2!', '3!', '4!', '5!', '6!', 'foo!', 'bar!'] {'a': 'apple', 'b': 'banana', 'o': 'orange'}
> python server.py localhost - - [22/Oct/2006 23:22:33] "POST /RPC2 HTTP/1.0" 200 - localhost - - [22/Oct/2006 23:22:33] "POST /RPC2 HTTP/1.0" 200 - localhost - - [22/Oct/2006 23:22:33] "POST /RPC2 HTTP/1.0" 200 - localhost - - [22/Oct/2006 23:22:33] "POST /RPC2 HTTP/1.0" 200 - localhost - - [22/Oct/2006 23:22:33] "POST /RPC2 HTTP/1.0" 200 - hello localhost - - [22/Oct/2006 23:22:33] "POST /RPC2 HTTP/1.0" 200 -
localhost - -... というのはアクセスログです。鬱陶しい場合はサーバインスタンス生成時に
s = SimpleXMLRPCServer.SimpleXMLRPCServer(('localhost', 12345), logRequests=False)
とすることでログを表示しないようになります。helloと表示されているのはクライアントがメソッド hello() を呼び出した結果です。
また、
SimpleXMLRPCServer.SimpleXMLRPCServer.allow_reuse_address=True
とすることで サーバ起動 -> 停止 -> サーバ起動 を短い時間で行ったときに出がちなエラー、Address already in use を殺しています。
気がついたことなど
- サーバに登録するインスタンスメソッド/関数はNone以外の値を返す必要がある
- hello()で返り値を書かなかったら呼び出し時に例外が起きた
- 文字列や数値だけではなく、リストや辞書なども結果として返すことができる
xmlrpclib
xmlrpclibを使ってみます。
基本的にはこれだけです。簡単ですね。以下ははてなの公開APIを使った例です。
import xmlrpclib s = xmlrpclib.ServerProxy('http://d.hatena.ne.jp/xmlrpc') r = s.hatena.getSimilarWord({'wordlist': ['Hatena', 'Python']}) print ', '.join(w['word'] for w in r['wordlist'])
実行結果
ReportLab, はてな伝説, ISBN:, 言語, アプリ, :detail, モジュール, VM, ビルド, Nokia, 付属, シンプル, Guido van Rossum, ...
再帰的にゲット(数が多くなるので最大でも10個ずつに限定)
# getword.py import sys import xmlrpclib def get(s, w, n, p=''): for i in s.hatena.getSimilarWord({'wordlist': w})['wordlist'][:10]: print p+i['word'].encode('euc-jp') if n: get(s, i['word'], n-1, p+'-') s = xmlrpclib.ServerProxy('http://d.hatena.ne.jp/xmlrpc') get(s, sys.argv[2:], int(sys.argv[1]))
実行例
> python getword.py 2 hatena apple GUI -MacOS --はてなダイアリーFAQ「その他のFAQ」 --2000年 --マルチタスク --NeXT --業界 --パーソナルコンピューター --Mac --リリース --クリエイター --Apple社 -1984年 --柴田あゆみ --Apple --Macintosh --6月13日 --金田美香 --10月7日 --ひまわり --水泳 --1949年 --3月29日 ...
# -*- coding: euc-jp -*- import xmlrpclib s = xmlrpclib.ServerProxy('http://d.hatena.ne.jp/xmlrpc') r = s.hatena.setKeywordLink({'body': 'はてなダイアリーのキーワードをリンクして!', 'score': 20, 'cname': ['book', 'movie'], 'a_target': '_blank', 'a_class': 'keyword'}) print r.encode('euc-jp')
実行結果
はてなダイアリーの<a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%a5%ad%a1%bc%a5%ef%a1%bc%a5%c9">キーワード</a>をリンクして!
はてなダイアリーキーワード連想語APIで取得したキーワードをはてなダイアリーキーワード自動リンクAPIでリンクする(全カテゴリのキーワードをリンクするためにcnameを省略)
# getword_setlink.py import sys import xmlrpclib s = xmlrpclib.ServerProxy('http://d.hatena.ne.jp/xmlrpc') for w in s.hatena.getSimilarWord({'wordlist': sys.argv[1:]})['wordlist']: print s.hatena.setKeywordLink({'body': w['word'].encode('euc-jp'), 'a_target': '_blank', 'a_class': 'keyword'}).encode('euc-jp')
実行例
> python getword_setlink.py りんご <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%c5%a3%b5%dc%cd%fd%b7%c3">釘宮理恵</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%a5%ea%a5%f3%a5%b4">リンゴ</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/TOWER%20RECORDS">TOWER RECORDS</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/HIPHOP">HIPHOP</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%a5%ec%a5%d3%a5%e5%a1%bc">レビュー</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/2004%c7%af">2004年</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%a5%a2%a5%eb%a5%d0%a5%e0">アルバム</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/ken">ken</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%c8%af%c9%bd">発表</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/bounce">bounce</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%a5%c0%a5%e1%a5%ec%a5%b3">ダメレコ</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/MC">MC</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/Da%2eMe%2eRecords">Da.Me.Records</a> <a class="keyword" target="_blank" href="http://d.hatena.ne.jp/keyword/%a5%ec%a1%bc%a5%d9%a5%eb">レーベル</a>
気がついたことなど