包装Pyro4名称服务器

时间:2013-11-15 23:57:46

标签: python multithreading multiprocessing pyro

我创建了一个类,允许我从脚本启动和停止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秒......

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