我创建了一个类,允许我从脚本启动和停止pyro名称服务器(即不必启动多个程序,如tutorial)。课程如下:
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秒钟。分析它告诉我,它是套接字方法连接需要1秒......
答案 0 :(得分:0)
我不知道到底出了什么问题,但您可以尝试我的新PyroMP包,它包含Pyro4 NameServer的包装器以及创建进程的简便方法。 您的示例将如下所示:
from threading import Thread
import time
from datetime import datetime
import Pyro4
import PyroMP
import PyroMP.log_server as log
class Dummy(object):
def __init__(self):
self.x = {}
def getX(self):
return self.x
class Worker(PyroMP.Service):
def run(self):
logger = self.get_logger()
for i in range(10):
a = datetime.now()
with Pyro4.Proxy("PYRONAME:dummy") as obj:
obj.getX()
logger.info("{}: {}".format(i, (datetime.now() - a).total_seconds()))
def main():
with PyroMP.NameServer(), log.LogServer():
log.set_loglevel("INFO")
daemon = Pyro4.Daemon()# make a Pyro daemon
obj = Dummy()
uri = daemon.register(obj) # register the greeting object as a Pyro object
ns = PyroMP.NameServer.locate()
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)
with Worker() as worker:
worker.run()
if __name__ == "__main__":
main()
输出结果为:
2014-02-19 18:56:32,877 - LogServer.WORKER - INFO - 0: 0.0
2014-02-19 18:56:32,892 - LogServer.WORKER - INFO - 1: 0.016
2014-02-19 18:56:32,892 - LogServer.WORKER - INFO - 2: 0.0
2014-02-19 18:56:32,894 - LogServer.WORKER - INFO - 3: 0.001
2014-02-19 18:56:32,940 - LogServer.WORKER - INFO - 4: 0.031
2014-02-19 18:56:32,956 - LogServer.WORKER - INFO - 5: 0.015
2014-02-19 18:56:32,956 - LogServer.WORKER - INFO - 6: 0.0