python多重处理,为每个进程创建实例并重用它

时间:2019-05-24 08:38:42

标签: python parallel-processing multiprocessing python-multiprocessing worker

我正在使用pytesseract通过多处理方法进行一些ocr。

该方法如下:

tess_api = PyTessBaseAPI()
Parallel(n_jobs=4)(delayed(execute)(image) for image in images)

具有功能:

def execute(image):
    tess_api.SetImage(image)
    text = tess_api.GetUTF8Text()

这将导致并发问题,因为工作进程1执行执行gettext()之前,工作进程1可能会覆盖映像

现在的想法是让每个工人一个PyTessBaseAPI实例。 主要的想法是做类似的事情:

tess_apis = [PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI()]

,然后将tess_api[0]移交给工作人员0,但我不知道如何在工作人员和实例之间建立连接。 有什么建议,或者什么是更好的方法? 因为我有成千上万张图像,所以我不想在execute函数中创建实例。

2 个答案:

答案 0 :(得分:1)

在每个工作进程开始使用Pool(initializer=...)初始化Tesseract对象之前,便开始读取其工作队列。

tess_api = None

def initialize_worker():
    global tess_api
    tess_api = PyTessBaseAPI()  # initialize a copy for this instance

def execute(image):
    tess_api.SetImage(image)
    text = tess_api.GetUTF8Text()

def main():
    with multiprocessing.Pool(initializer=initialize_worker) as p:
        for result in p.imap_unordered(images, chunksize=10):
            # ...

这仅在您使用实际流程时才有效;如果您使用的是线程(考虑到Tesseract是C并会发布GIL,这可能会起作用),则可以使用contextvars / threading.local

答案 1 :(得分:1)

Pool(initializer=...)可以按照提及的方式工作。但是,如果您想做更复杂的事情,建议您使用Ray

然后将其表示为

import ray

ray.init()

@ray.remote
class Worker(object):
    def __init__(self):
        self.tess_api = PyTessBaseAPI()

    def execute(self, image):
        self.tess_api.SetImage(image)
        return self.tess_api.GetUTF8Text()

# Create several Worker actors.
workers = [Worker.remote() for _ in range(4)]

# Execute tasks on them in parallel.
result_ids = [worker.execute.remote(image) for worker in workers]

# Get the results
results = ray.get(result_ids)

您可以阅读有关Ray in the documentation的更多信息。请注意,我帮助开发Ray。