5

我正在使用必须循环执行某些任务的 xmlrpc 服务器。我使用 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

我应该如何加入这两个过程,以使它们各自的加入不会阻塞?

(我对“加入”感到很困惑。为什么它会阻塞,我已经用谷歌搜索了但找不到关于加入使用的有用解释。有人可以向我解释一下吗?)

问候

4

2 回答 2

11

你真的需要在一个单独的进程中运行 Twisted 吗?这对我来说看起来很不寻常。

尝试将 Twisted 的 Reactor 视为您的主循环 - 并将您需要的所有内容挂起 - 而不是尝试将 Twisted 作为后台任务运行。

执行此类操作的更正常方式是使用 Twisted 的 .callLater 或将 LoopingCall 对象添加到 Reactor。

例如

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()
于 2009-09-04T12:06:34.700 回答
3

嘿 asdvawev - 多处理中的 .join() 就像线程中的 .join() 一样工作 - 这是主线程运行以等待工作线程关闭的阻塞调用。如果 worker 永远不会关闭,那么 .join() 将永远不会返回。例如:

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

对此调用 run 意味着 join() 永远不会返回。通常为了防止这种情况发生,我将使用传递给子进程的 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)

或者,如果您的工作被封装在一个队列中 - 您可以简单地让子进程从队列中工作,直到它遇到一个哨兵(通常是队列中的 None 条目)然后关闭。

这两个建议都意味着在调用 .join() 之前,您可以发送设置事件,或插入哨兵,当调用 join() 时,进程将完成当前任务,然后正确退出。

于 2009-09-04T13:29:24.070 回答