我创建了一个类以允许我从脚本启动和停止 pyro 名称服务器(即不必启动多个程序,例如教程中的程序)。课程如下:
class NameServer(Pyro4.threadutil.Thread):
def __init__(self, host, isDeamon, port=0, enableBroadcast=True,
bchost=None, bcport=None, unixsocket=None, nathost=None, natport=None):
super(NameServer,self).__init__()
self.setDaemon(isDeamon)
self.host=host
self.started=Pyro4.threadutil.Event()
self.unixsocket = unixsocket
self.port = port
self.enableBroadcast = enableBroadcast
self.bchost = bchost
self.bcport = bcport
self.nathost = nathost
self.natport = natport
#This code is taken from Pyro4.naming.startNSloop
self.ns_daemon = Pyro4.naming.NameServerDaemon(self.host, self.port, self.unixsocket,
nathost=self.nathost, natport=self.natport)
self.uri = self.ns_daemon.uriFor(self.ns_daemon.nameserver)
internalUri = self.ns_daemon.uriFor(self.ns_daemon.nameserver, nat=False)
self.bcserver=None
self.ns = self.ns_daemon.nameserver
if self.unixsocket:
hostip = "Unix domain socket"
else:
hostip = self.ns_daemon.sock.getsockname()[0]
if hostip.startswith("127."):
enableBroadcast=False
if enableBroadcast:
# Make sure to pass the internal uri to the broadcast responder.
# It is almost always useless to let it return the external uri,
# because external systems won't be able to talk to this thing anyway.
bcserver=Pyro4.naming.BroadcastServer(internalUri, self.bchost, self.bcport)
bcserver.runInThread()
def run(self):
try:
self.ns_daemon.requestLoop()
finally:
self.ns_daemon.close()
if self.bcserver is not None:
self.bcserver.close()
def startNS(self):
self.start()
def stopNS(self):
self.ns_daemon.shutdown()
if self.bcserver is not None:
self.bcserver.shutdown()
现在,如果我运行以下脚本
import socket
import Pyro4
from threading import Thread
import time
from multiprocessing import Process
import sys
from datetime import datetime
HMAC_KEY = "1234567890"
Pyro4.config.HMAC_KEY = HMAC_KEY
sys.excepthook = Pyro4.util.excepthook
[... definition of class NameServer given previously ...]
class Dummy:
x = {}
def getX(self):
return self.x
class Worker(Process):
def run(self):
Pyro4.config.HMAC_KEY = HMAC_KEY
sys.excepthook = Pyro4.util.excepthook
for i in range(10):
a = datetime.now()
with Pyro4.Proxy("PYRONAME:dummy") as obj:
obj.getX()
print i, (datetime.now() - a).total_seconds()
def main():
nameserver = NameServer(socket.gethostbyname(socket.gethostname()), False)
nameserver.startNS()
daemon=Pyro4.Daemon(socket.gethostname(), port=7676) # make a Pyro daemon
obj = Dummy()
uri=daemon.register(obj) # register the greeting object as a Pyro object
nameserver.ns.register("dummy", uri) # register the object with a name in the name server
thread = Thread(target = daemon.requestLoop)
thread.setDaemon(1)
thread.start()
time.sleep(1)
worker = Worker()
worker.start()
if __name__ == "__main__":
main()
我得到以下输出:
0 1.078
1 1.05
2 1.013
3 1.037
4 1.013
5 1.087
6 1.063
7 1.1
8 1.063
9 1.05
但是,如果我将此代码作为两个不同的程序运行而不使用我的 NameServer 类,我不会得到这些延迟。例如,运行第一个脚本:
import Pyro4
import sys
HMAC_KEY = "1234567890"
Pyro4.config.HMAC_KEY = HMAC_KEY
sys.excepthook = Pyro4.util.excepthook
class Dummy:
x = {}
def getX(self):
return self.x
def main():
obj = Dummy()
Pyro4.Daemon.serveSimple({obj: "dummy"}, ns = False)
if __name__ == "__main__":
main()
和第二个脚本
import Pyro4
from multiprocessing import Process
import sys
from datetime import datetime
HMAC_KEY = "1234567890"
Pyro4.config.HMAC_KEY = HMAC_KEY
sys.excepthook = Pyro4.util.excepthook
class Worker(Process):
def run(self):
Pyro4.config.HMAC_KEY = HMAC_KEY
sys.excepthook = Pyro4.util.excepthook
for i in range(10):
a = datetime.now()
with Pyro4.Proxy("[the URI given by Pyro when running script 1]") as obj:
obj.getX()
print i, (datetime.now() - a).total_seconds()
def main():
worker = Worker()
worker.start()
if __name__ == "__main__":
main()
我得到以下结果
0 0.053
1 0.049
2 0.051
3 0.05
4 0.013
5 0.049
6 0.051
7 0.05
8 0.013
9 0.049
...第一种方法有什么问题?我不明白为什么每次 Pyro 调用都会延迟 1 秒。分析它告诉我,它是套接字方法 connect 需要 1 秒......