繁体   English   中英

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

[英]python multiprocessing, make instance per process and reuse it

我正在使用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()

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

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

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

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

在每个工作进程开始读取其工作队列之前,使用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

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的更多信息。 请注意,我帮助开发Ray。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM