简体   繁体   English

使用twisted的反应器进行Python多处理

[英]Python multiprocessing with twisted's reactor

I am working on a xmlrpc server which has to perform certain tasks cyclically. 我正在开发一个xmlrpc服务器,它必须周期性地执行某些任务。 I am using twisted as the core of the xmlrpc service but I am running into a little problem: 我使用twisted作为xmlrpc服务的核心,但我遇到了一个小问题:

class cemeteryRPC(xmlrpc.XMLRPC):

    def __init__(self, dic):
        xmlrpc.XMLRPC.__init__(self)


    def xmlrpc_foo(self):
        return 1


    def cycle(self):
        print "Hello"
        time.sleep(3)


class cemeteryM( base ):

    def __init__(self, dic):   # dic is for cemetery
        multiprocessing.Process.__init__(self)
        self.cemRPC = cemeteryRPC()


    def run(self):
        # Start reactor on a second process
        reactor.listenTCP( c.PORT_XMLRPC, server.Site( self.cemRPC ) )
        p = multiprocessing.Process( target=reactor.run )
        p.start()

        while not self.exit.is_set():
            self.cemRPC.cycle()
            #p.join()


if __name__ == "__main__":

    import errno
    test = cemeteryM()
    test.start()

    # trying new method
    notintr = False
    while not notintr:
        try:
            test.join()
            notintr = True 
        except OSError, ose:
            if ose.errno != errno.EINTR:
                raise ose
        except KeyboardInterrupt:
            notintr = True

How should i go about joining these two process so that their respective joins doesn't block? 我应该如何加入这两个过程,以便它们各自的连接不会阻塞?

(I am pretty confused by "join". Why would it block and I have googled but can't find much helpful explanation to the usage of join. Can someone explain this to me?) (我对“加入”非常困惑。为什么它会阻止我用谷歌搜索但是找不到很多有用的解释加入的用法。有人能解释一下吗?)

Regards 问候

Do you really need to run Twisted in a separate process? 你真的需要在一个单独的进程中运行Twisted吗? That looks pretty unusual to me. 这看起来很不寻常。

Try to think of Twisted's Reactor as your main loop - and hang everything you need off that - rather than trying to run Twisted as a background task. 试着把Twisted的Reactor想象成你的主循环 - 并挂掉你需要的一切 - 而不是试图将Twisted作为后台任务运行。

The more normal way of performing this sort of operation would be to use Twisted's .callLater or to add a LoopingCall object to the Reactor. 执行此类操作的更常规方法是使用Twisted的.callLater或将LoopingCall对象添加到Reactor。

eg 例如

from twisted.web import xmlrpc, server
from twisted.internet import task
from twisted.internet import reactor

class Example(xmlrpc.XMLRPC):          
    def xmlrpc_add(self, a, b):
        return a + b

    def timer_event(self):
        print "one second"

r = Example()
m = task.LoopingCall(r.timer_event)
m.start(1.0)

reactor.listenTCP(7080, server.Site(r))
reactor.run()

Hey asdvawev - .join() in multiprocessing works just like .join() in threading - it's a blocking call the main thread runs to wait for the worker to shut down. 嘿asdvawev - .join()在多处理中就像线程中的.join()一样工作 - 它是一个阻塞调用,主线程运行等待工作者关闭。 If the worker never shuts down, then .join() will never return. 如果工作者永远不会关闭,那么.join()将永远不会返回。 For example: 例如:

class myproc(Process):
    def run(self):
        while True:
            time.sleep(1)

Calling run on this means that join() will never, ever return. 调用run on this意味着join()永远不会返回。 Typically to prevent this I'll use an Event() object passed into the child process to allow me to signal the child when to exit: 通常为了防止这种情况,我将使用传递给子进程的Event()对象来允许我发信号通知子进程何时退出:

class myproc(Process):
    def __init__(self, event):
        self.event = event
        Process.__init__(self)
    def run(self):
        while not self.event.is_set():
            time.sleep(1)

Alternatively, if your work is encapsulated in a queue - you can simply have the child process work off of the queue until it encounters a sentinel (typically a None entry in the queue) and then shut down. 或者,如果您的工作被封装在一个队列中 - 您可以让子进程在队列中工作,直到它遇到一个sentinel(通常是队列中的None条目),然后关闭。

Both of these suggestions means that prior to calling .join() you can send set the event, or insert the sentinel and when join() is called, the process will finish it's current task and then exit properly. 这两个建议意味着在调用.join()之前你可以发送set事件,或者插入sentinel,当调用join()时,进程将完成它的当前任务,然后正确退出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM