Pyro4の使い方

Pyro4

異なるアーキテクチャ間でリモートでメソッドコールできるライブラリ
あんまり日本語の情報がないのでメモ程度に書いておく

日本語の情報はほとんどないから諦めて英語で探す
https://pythonhosted.org/Pyro4/
公式のGithubのExampleとか参考にする
https://github.com/delmic/Pyro4/

インストール

1$ pip install Pyro4

Pyroだと古いバージョンが入るので注意がいる

ネームサーバーなし

ネームサーバーがあると裏で勝手に名前解決してくれるので楽になるけどなしでもできる

基本的に自分がクライアント側になるはず

ホスト側

 1import Pyro4
 2
 3def getHoge():
 4    return "test"
 5 
 6Pyro4.Daemon.serveSimple(
 7    {getHoge:'HogeMethod'},
 8    host="自分のIP",
 9    port=9090,#適当なポート
10    ns=False,
11)

クライアント側

1import Pyro4
2
3name = "HogeMethod"
4ip = "相手のIP"
5port = 9090#適当なポート 合わせる
6s = "PYRO:%s@%s:%s" % (name, ip, port)
7remote = Pyro4.Proxy(s)
8remote.getHoge()

みたいな感じで呼べる

ネームサーバあり

ネームサーバ

用意されてるものを使う場合は

1$ python -m Pyro4.naming

随時オプションをつける
WindowsだとCtrl+Cとかで抜けられないので不便
自分でコードを書くなら

 1import Pyro4
 2import socket
 3 
 4host = socket.gethostbyname(socket.gethostname())#VMの仮想NIC取りに行ったりするから微妙
 5host = "ダメなら手動で入れる"
 6port = 9900
 7url, daemon, bcserver = Pyro4.naming.startNS(
 8	host = host,
 9	port = port,
10)
11
12print "ready", url
13print "listening %s:%s" % (host, port)
14#適当にスレッド化して中断出来るようにしておく
15import threading
16thread = threading.Thread(target = daemon.requestLoop)
17thread.setDaemon(True)
18thread.start()
19while True: pass

確認する

1$ python -m Pyro4.nsc list

引数あり

1$ python -m Pyro4.nsc -n 192.168.1.114 -p 9900 list
2--------START LIST
3Pyro.NameServer --> PYRO:Pyro.NameServer@192.168.1.114:9900
4    metadata: (u'class:Pyro4.naming.NameServer',)
5robot --> PYRO:obj_91e53083bd114775adeaed91e73018bd@localhost:32977
6--------END LIST

同じようにpingも飛ばせる

ホスト側

単一ノード上なら動くけど他端末との通信に失敗する
Pyro4.Daemon() メソッドの引数がネームサーバーに登録されるから忘れると失敗する

 1# -*- encoding:utf-8 -*-
 2 
 3import Pyro4
 4import socket
 5 
 6#####################################################
 7#
 8# リモートから呼ばれるメソッド
 9#
10#####################################################
11 
12class PyroTest1(object):
13	def hello(self):
14		return "Hello World"
15	def world(self):
16		return "world"
17
18class PyroTest2(object):
19	def hello(self):
20		return "H"
21	def world(self):
22		return "W"
23 
24#####################################################
25 
26#ローカルIP取得
27def getLocalIP():
28	import socket
29	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
30	s.connect(("8.8.8.8",80))
31	ip = s.getsockname()[0]
32	s.close()
33 
34	return ip
35 
36#ネームサーバに登録する時の元情報
37daemon = Pyro4.Daemon(
38	host = "192.168.133.105",
39	port = port,
40)
41 
42#ネームサーバ情報
43nameserver = Pyro4.locateNS(
44	host = getLocalIP(),
45	port = port,
46)
47#登録
48nameserver.register("test1" ,daemon.register(PyroTest1))
49nameserver.register("test2" ,daemon.register(PyroTest2))
50 
51print "everything ready ok"
52import threading
53thread = threading.Thread(target = daemon.requestLoop)
54thread.setDaemon(True)
55thread.start()
56while True: pass

クライアント側

呼び出して終わり

 1# -*- encoding:utf-8 -*-
 2 
 3import Pyro4
 4 
 5nameserver = Pyro4.locateNS(
 6	host = "192.168.1.114",
 7	port = 9090
 8)
 9 
10uri = nameserver.lookup("test1")
11print uri
12obj = Pyro4.Proxy(uri)
13print obj.hello()