threading.Thread反对多处理.Process

时间:2015-06-12 14:17:52

标签: python multithreading multiprocessing

所以最近我遇到了以下问题:我必须创建一个处理请求的服务器,以便在主进程使用此值时更新某些值。 所以这里,服务器处理功能在子进程中,我不能在我想要的时候停止它。

为了测试threading.Threadmultiprocessing.Process之间我的问题的最佳解决方案,我在以下程序中做了以下几点:

import multiprocessing
import time
import threading

class SubProcess(multiprocessing.Process):

    def __init__(self, source):
        self.source = source
        super(SubProcess, self).__init__()

    def run(self):
        while 1:
            time.sleep(1) # Waiting for request...
            self.source.somevar["anotherkey"].append(5)
            print "My subprocess : ", id(self.source), id(self.source.somevar), self.source.somevar

class SubThread(threading.Thread):

    def __init__(self, source):
        self.source = source
        super(SubThread, self).__init__()

    def run(self):
        while 1:
            time.sleep(1) # Waiting for request...
            self.source.somevar["anotherkey"].append(5)
            print "My subthread : ", id(self.source), id(self.source.somevar), self.source.somevar

class Source:

    def __init__(self):
        self.somevar = {"akey": "THE key", "anotherkey": [5]}

    def start_process(self):
        self.process = SubProcess(self)
        self.process.start()

    def stop_process(self):
        self.process.terminate()

    def start_thread(self):
        self.thread = SubThread(self)
        self.thread.start()

    def stop_thread(self):
        # self.thread.stop() # What the hell should i put here
        pass

s = Source()

s.start_process()
time.sleep(2)
print "End : ", id(s), id(s.somevar), s.somevar
s.stop_process()

s.start_thread()
time.sleep(2)
print "End : ", id(s), id(s.somevar), s.somevar
s.stop_thread() # Obviously, thread never ends...

所以threading.Thread修改了原始s.somevar,但我无法阻止它,而multiprocessing.Process没有修改原s.somevar,但我可以停止它

我正在寻找一个可以停止线程的解决方案(使用SIGTERM),线程可以使用标准库修改原始类Source。有没有解决方案?

2 个答案:

答案 0 :(得分:1)

要杀死线程,你需要在子线程和主线程之间做一些合作。使用示例代码,您可以使用threading.Event

class SubThread(threading.Thread):

    def __init__(self, source):
        self.source = source
        self.should_stop = threading.Event()
        super(SubThread, self).__init__()

    def run(self):
        while not self.should_stop.wait(1):
            #time.sleep(1) # No need to sleep, since we're waiting for 1 second above.
            self.source.somevar["anotherkey"].append(5)
            print "My subthread : ", id(self.source), id(self.source.somevar), self.source.somevar

    def stop(self):
        """ Call this to abort the thread. """
        self.should_stop.set()

这并不像process.terminate()那样立即终止,因为在线程停止之前你必须实际调用should_stop.wait()

要使SubProcess正常工作,您需要使用进程安全的共享变量。 multiprocessing模块为此提供multiprocessing.Manager;它允许您在管理器进程中创建共享变量。你正在更新dict的方式实际上有点难以正确处理,因为在Proxy中从Manager对象中更改可变值的一些限制(请参阅请注意here)。您必须明确地将更新的列表重新分配给dict才能正确更新dict:

class SubProcess(multiprocessing.Process):

    def __init__(self, source):
        self.source = source
        super(SubProcess, self).__init__()

    def run(self):
        while 1:
            time.sleep(1) # Waiting for request...
            # Can't do this with a Manager.dict
            #self.source.somevar["anotherkey"].append(5)

            # Do this instead. You'd need to do it with SubThread.run, too.
            l = self.source.somevar["anotherkey"]
            l.append(5)
            self.source.somevar["anotherkey"] = l
            print "My subprocess : ", id(self.source), id(self.source.somevar), self.source.somevar

class Source:

    def __init__(self):
        self.m = multiprocessing.Manager()
        # somevar is now process-safe.
        self.somevar = self.m.dict({"akey": "THE key", "anotherkey": [5]})

    # The rest is the same

答案 1 :(得分:0)

不,没有。有关选项的讨论,请参阅Is there any way to kill a Thread in Python? - 但这些是合作的!如果无法做到这一点,请使用多处理+消息在本地更新状态副本。