0

我试图结合我从两个不同的 python 问题中得到的答案。

这是第一个问题和答案。基本上我只想生成两个线程,一个到 powerDown(),另一个到 powerUp(),其中 powerUp() 挂起 powerDown()

如何在python中的同一对象的另一个线程中生成一个线程?

import threading

class Server(threading.Thread):
    # some code
    def run(self):
        self.reboot()

    # This is the top level function called by other objects
    def reboot(self):
        # perhaps add a lock
        if not hasattr(self, "_down"):
            self._down = threading.Thread(target=self.__powerDown)
            self._down.start()
            up = threading.Thread(target=self.__powerUp)
            up.start()

    def __powerDown(self):
        # do something

    def __powerUp(self):
        if not hasattr(self, "_down"):
            return
        self._down.join()
        # do something
        del self._down

这是第二个问题和答案。基本上我想启动一个线程,然后调用对象的一个​​函数。

如何在正在运行的 Python 线程上调用函数

import queue
import threading

class SomeClass(threading.Thread):
    def __init__(self, q, loop_time = 1.0/60):
        self.q = q
        self.timeout = loop_time
        super(SomeClass, self).__init__()

    def onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def run(self):
        while True:
            try:
                function, args, kwargs = self.q.get(timeout=self.timeout)
                function(*args, **kwargs)
            except queue.Empty:
                self.idle()

    def idle(self):
        # put the code you would have put in the `run` loop here 

    def doSomething(self):
        pass

    def doSomethingElse(self):
        pass

这是组合的想法代码。基本上我想产生一个线程,然后排队执行一个函数,在这种情况下是reboot()。reboot() 依次创建两个线程,powerDown() 和 powerUp() 线程,其中 powerDown() 挂起 powerUp()

import threading
import Queue

class Server(threading.Thread):
    def __init__(self, q, loop_time = 1.0/60):
        self.q = q
        self.timeout = loop_time
        super(Server, self).__init__()

    def run(self):
        while True:
            try:
                function, args, kwargs = self.q.get(timeout=self.timeout)
                function(*args, **kwargs)
            except queue.Empty:
                self.idle()

    def idle(self):
        # put the code you would have put in the `run` loop here 

    # This is the top level function called by other objects
    def reboot(self):
        self.__onthread(self.__reboot)

    def __reboot(self):
        if not hasattr(self, "_down"):
            self._down = threading.Thread(target=self.__powerDown)
            self._down.start()
            up = threading.Thread(target=self.__powerUp)
            up.start()

    def __onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def __powerDown(self):
        # do something

    def __powerUp(self):
        if not hasattr(self, "_down"):
            return
        self._down.join()
        # do something
        del self._down

一切正常,除非我创建两个服务器子类。

class ServerA(Server):
    pass

class ServerB(Server):
    pass

这是 instatiats 两个子类的代码,并调用 start() 和 reboot 函数

serverA = ServerA(None)
serverB = ServerB(None)
serverA.start()
serverB.start()
serverA.reboot()
serverB.reboot()

我希望 serverA.reboot() 和 serverB.reboot() 同时发生,这是我想要的,但他们不会!serverB.reboot() 在 serverA.reboot() 完成后执行。也就是说,如果我把打印语句,我得到

serverA started
serverB started
serverA.reboot() called
serverA.__powerDown called
serverA.__powerUp called
serverB.reboot() called
serverB.__powerDown called
serverB.__powerUp called

我知道 ServerA 需要更长的时间才能重新启动,所以我期待这样的事情

serverA started
serverB started
serverA.reboot() called
serverB.reboot() called
serverA.__powerDown called
serverB.__powerDown called
serverB.__powerUp called
serverA.__powerUp called

我希望这是有道理的。如果是这样,为什么我的 reboot() 函数没有同时发生?

4

1 回答 1

1

为什么在您None 首先期望队列对象时发送?这会导致一个异常,它抱怨 None 类型对象没有 get 方法。除此之外,您希望在run方法中处理的异常是Queue.Empty而不是queue.Empty

这是修改后的代码及其在我的机器上的输出:

import threading
import Queue

class Server(threading.Thread):
    def __init__(self, title, q, loop_time = 1.0/60):
        self.title = title
        self.q = q
        self.timeout = loop_time
        super(Server, self).__init__()

    def run(self):
        print "%s started" % self.title
        while True:
            try:
                function, args, kwargs = self.q.get(timeout=self.timeout)
                function(*args, **kwargs)

            except Queue.Empty:
                # print "empty"
                self.idle()

    def idle(self):
        pass
        # put the code you would have put in the `run` loop here 

    # This is the top level function called by other objects
    def reboot(self):
        self.__onThread(self.__reboot)

    def __reboot(self):
        if not hasattr(self, "_down"):
            self._down = threading.Thread(target=self.__powerDown)
            self._down.start()
            up = threading.Thread(target=self.__powerUp)
            up.start()

    def __onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def __powerDown(self):
        # do something
        print "%s power down" % self.title
        pass

    def __powerUp(self):
        print "%s power up" % self.title

        if not hasattr(self, "_down"):
            return

        self._down.join()
        # do something
        del self._down

class ServerA(Server):
    pass

class ServerB(Server):
    pass

def main():
    serverA = ServerA("A", Queue.Queue())
    serverB = ServerB("B", Queue.Queue())
    serverA.start()
    serverB.start()
    serverA.reboot()
    serverB.reboot()

if __name__ == '__main__':
    main()

输出:

A started
B started

B power down
A power down
B power up
A power up
于 2013-09-26T22:07:36.793 回答