Python多进程:Pool.map()似乎根本没有调用函数

3

我对多线程不太熟悉,如果这很基础,我很抱歉。我有一些函数可以OCR图像文件,我想将任务多线程化。该函数不返回任何内容,但仅保存OCR数据集的文本。代码如下:

start_time = time.time()
path = 'C:\\Users\\RNCZF01\\Documents\\Cameron-Fen\\Economics-Projects\\Patent-project\\similarity\\Patents\\OCR-test'
listfiles = os.listdir(path)

filterfiles = [p for p in listfiles if p[-4:] == '.tif']

pool = Pool(processes=2)

result = pool.map(OCRimage,filterfiles)

pool.close()
pool.join()

print("--- %s seconds ---" % (time.time() - start_time))

当我运行代码时,看起来它似乎卡在了pool.map()上。我运行了30分钟,这比试用过程所需的时间要长得多,结果没有产生任何输出。我测试了我的OCRimage函数,似乎没有进入函数一次(使用print(1)作为我的OCRimage代码的第一行)。我想知道是否有人可以帮我解决。谢谢,Cameron
编辑(添加了OCRimage函数):
OCRimage函数如下:
def OCRimage(f):
    #This runs the magick bash script which splits a multi-image tif into multiple single image tiffs
    process = subprocess.Popen(["magick", path + "\\" + f, path + "\\temp\\%d.tif"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    print(process.communicate()[0])

    #finds the number of pages for each tiff file (this might not be necassary but the all files in directory python command could access files randomly)
    max1 = -1
    for filename in os.listdir(path+'\\temp'):    
        if (max1 < int(filename[0:-4])):
            max1 = int(filename[0:-4])
    max1 = max1 + 1

    text = ""
    for each in range(0,max1):
        im = Image.open(path + "\\temp\\"+ str(each) + ".tif")
        text = text + pytesseract.image_to_string(im)
    with open(path + "\\result\\OCR-"+f[0:-4]+".txt", 'w') as file:
        file.write(text)    

    for f in os.listdir(path+'\\temp'):
        os.remove(path + '\\temp\\' + f)

编辑2:以下是所有的导入

import time
import subprocess
import os
import pytesseract
from PIL import Image

from multiprocessing import Pool
import multiprocessing
countcpus = multiprocessing.cpu_count()

编辑3:

仅运行OCRimage(f)本身是可以正常工作的。我不再使用多线程代码,而是使用以下代码:

path = 'C:\\Users\\RNCZF01\\Documents\\Cameron-Fen\\Economics-Projects\\Patent-project\\similarity\\Patents\\OCR-test'
for p in os.listdir(path):
    OCRimage(p)

代码的其余部分也不会将OCR文本文件打印到输出文件中。 - cfen
没有一种可重现的方式,帮助你变得非常困难,尝试创建一个最小完整可重现的示例。证明“filterfiles”不为空,查看“OCRimage”的代码(即使它只是打印)等。 - Nir Alfasi
将内容写入文件也不起作用,就像将内容打印到标准输出一样,什么都没有发生,文件也没有被创建。 - cfen
filterfiles 不为空,我打印了它的内容。 - cfen
这可能是一个Windows问题。当我将import中的multiprocessing更改为multiprocessing.dummy时,它可以正常运行。 - cfen
显示剩余6条评论
1个回答

1
这是一个最小、完整、可验证的示例(Minimal, Complete, and Verifiable Example),似乎表明问题必须在您的OCRimage函数中(有关真正的问题,请参见下面的Windows部分):
from multiprocessing import Pool

def OCRimage(file_name):
    print "file_name = %s" % file_name

filterfiles = ["image%03d.tif" % n for n in range(5)]

pool = Pool(processes=2)
result = pool.map(OCRimage, filterfiles)

pool.close()
pool.join()

输出

file_name = image000.tif
file_name = image001.tif
file_name = image002.tif
file_name = image003.tif
file_name = image004.tif

我建议对OCRimage的开头进行以下更改:
def OCRimage(file_name):
    print "file_name = %s" % file_name
    src = os.path.join([path, file_name])
    dst = os.path.join([path, 'temp', '%d.tif'])
    command_list = ['magick', src, dst]
    # This runs the magick bash script which splits a multi-image tif into
    # multiple single image tiffs
    process = subprocess.Popen(command_list,
                               shell=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    output, errors = process.communicate()
    if process.returncode != 0:
        print "Image processing failed for %s: %s" % (file_name, errors)
        return
    # The rest of your code goes here

重要的是要验证子进程的返回代码是否为零。如果不是零,您真的想查看错误字符串。
Windows
当我在Windows上运行mcve时,我得到了这个异常:
RuntimeError: 
            Attempt to start a new process before the current process
            has finished its bootstrapping phase.

            This probably means that you are on Windows and you have
            forgotten to use the proper idiom in the main module:

                if __name__ == '__main__':
                    freeze_support()
                    ...

            The "freeze_support()" line can be omitted if the program
            is not going to be frozen to produce a Windows executable.
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python27\lib\multiprocessing\forking.py", line 380, in main

当我将mcve更改为以下内容时,它起作用了:
from multiprocessing import Pool

def OCRimage(file_name):
    print "file_name = %s" % file_name

def main():
    filterfiles = ["image%03d.tif" % n for n in range(5)]
    pool = Pool(processes=2)
    result = pool.map(OCRimage, filterfiles)
    pool.close()
    pool.join()

if __name__ == '__main__':
    main()

所以问题在于,当我不使用多线程时,OCRimage运行良好。 - cfen
至少对我来说,问题在于result = pool.map(OCRimage, filterfiles)无法正常工作。即使我使用OCRimage(f): return f**2。我使用的是Python 2.7。 - cfen
你运行了我回答顶部的 [mcve] (最小完备可复现示例) 吗?它是否生成了预期输出? - user3657941
它并没有。我尝试运行了你的例子。我认为这是一个Windows问题,因为我的代码在它被设计用于的Linux集群上运行得很好。 - cfen
在你的Windows机器上运行python --version命令的输出是什么? - user3657941
我不得不将代码放在一个函数中,才能让[mcve]在Windows上正常工作。请参见我的更改。 - user3657941

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接