Python如何混用进程池和线程池

27 阅读1分钟

下面是探索出来的一种比较安全简易的方法。

import time
from concurrent.futures.process import ProcessPoolExecutor
from concurrent.futures.thread import ThreadPoolExecutor
from multiprocessing import Manager
from multiprocessing.managers import SyncManager
from queue import PriorityQueue

_sentinel = None

class MyManager(SyncManager):
    pass
MyManager.register("PriorityQueue", PriorityQueue)

def Manager():
    m = MyManager()
    m.start()
    return m

class MyClass:
    def thread_func(self, item, q1, q2):
        print('item: {} in thread'.format(item))
        q1.put(Exception("test exception"))

    def _process(self, q0, q1, q2):
        thread_pool = ThreadPoolExecutor(2)
        while True:
            if not q0.empty():
                item = q0.get()
                if item == _sentinel:
                    q0.put(_sentinel)
                    print("receive sentinel, over process")
                    break
                thread_pool.submit(self.thread_func, item, q1, q2)
            else:
                time.sleep(1)

    def run(self):
        process_pool = ProcessPoolExecutor(2)
        process_rets = []
        q0 = Manager().Queue(maxsize=4)
        q1 = Manager().Queue(maxsize=4)
        q2 = Manager().PriorityQueue(4)
        for i in range(2):
            process_rets.append(process_pool.submit(self._process, q0, q1, q2))

        q0.put(11)
        q0.put(22)
        q0.put(33)
        q0.put(44)
        q0.put(_sentinel)

        q2.put(2)
        q2.put(1)
        q2.put(4)
        q2.put(3)

        for ret in process_rets:
            ret.result()

        print('q length:', q1.qsize())

        # while not q.empty():         #    q.get().result()         print(q2.get())

if __name__ == "__main__":
    obj = MyClass()
    obj.run()