用于元组列表的Python pool.map

时间:2017-08-14 22:03:53

标签: python multithreading multiprocessing threadpool

我遇到了以下问题。我正在尝试重构我的代码,以便使用多线程处理API调用。我的核心数据是以下格式的元组简单列表:

lst = [('/Users/sth/photo1.jpg',
      '/Users/sth/photo2'),
      ('/Users/sth/photo1.jpg',
      '/Users/sth/photo3'), (...)]

我使用的功能使用 lst 列表并通过需要一对照片的API处理它。毕竟为每对返回一个数字。到目前为止,我正在使用循环将元组放入我的函数并生成所提到的数字。我希望以一种方式对整个计算进行并列化,即一个进程占用我的列表的一部分并调用批处理中的元组的函数。为此,我尝试将池函数用于多处理模块:

from multiprocessing.dummy import Pool as ThreadPool 
pool = ThreadPool(2)
results = pool.map(score_function, lst)

但是,发生以下错误:

IOError: [Errno 2] No such file or directory: 'U'

这里发生了一些奇怪的事情。它试图将我的元组中的单个字符视为参数。任何想法如何正确地做到这一点?

谢谢

@edit

缺少score_function定义是我的不好。让我更新一下问题:

def score_function(pairs):
    score_list = list()

    for pair in pairs:
       score = findElement(target = pair[0], source = pair[1])
       score_list.append([pair[0], pair[1], score])

    return score_list

其中findElement定义为:

def findElement(target, source):

    with open(source, 'rb') as source_:
        source_bytes = source_.read()

    with open(target, 'rb') as target_:
        target_bytes = target_.read()

    score = API_request(target_bytes = target_bytes,
                        source_bytes = source_bytes)
    return score

3 个答案:

答案 0 :(得分:1)

在不知道您的score_function以及如何定义和访问它的情况下,我猜您有类似

的内容
def score_function(param):
    with open(param[1], "r") as fp:
        ....
在那里。

错误表明你的param根本不是一个元组,而是一个字符串(param [1],如果param是元组,则是第二个元素,而param [1],如果param是一个字符串,则是第二个字符,在你的情况下U来自/ Users ...)。放

print param

那里看看它是什么。你的lst都是错的,并且缺少括号,pool.map将它展平并将每个单独的组件作为字符串发送到你的函数,或者你的lst中有一个不是元组的违规条目。例如,如果有一个条目并且您忘记在其周围加上括号,它会将每个单独的字符串作为参数发送

lst = [('/Users/bar/photo1.jpg', '/Users/bar/photo2'),
       ('/Users/bar/photo2.jpg', '/Users/bar/photo3'),
       '/Users/bar/photo3.jpg', '/Users/bar/photo4',
       (...., .....), (...., .....)]

它能够处理前两个但是第三个(和第四个,因为它现在是一个单独的条目而不是元组中的第二个组件)将导致你现在得到的错误。无论哪种方式,打印出score_function收到的参数都应该可以帮助您找出问题所在。您对pool.map的使用是正确的,它应该可以正常工作,假设您的输入符合您的预期。

答案 1 :(得分:1)

你的问题是for循环。它将你的元组分解为单个字符串。这样做,它应该工作:

def score_function(pairs):
    score_list = list()

    score = findElement(target = pairs[0], source = pairs[1])
    score_list.append([pairs[0], pairs[1], score])

    return score_list

您可能认为您的score_function会收到lst变量作为参数。这不会发生。 lst需要是一个列表,就像你的情况一样,pool.map自动将它拆分为单个元素,并将一个元素精确地提供给score_function,并一直这样做,直到整个列表被处理为止你的工人。每次对工作者的调用都只接收它应该处理的一个元素作为参数。你的单个元素是元组(path1,path2),当你在这个元组上调用for时,你的循环中只接收一个单独的路径(字符串),而对[1]只是这个字符串的第二个字符。

希望这会有所帮助。

答案 2 :(得分:1)

您可以像这样使用在地图中插入的starmap函数:

from multiprocessing import Pool 
pool = Pool(processes=4)
results = pool.starmap(score_function, lst)
pool.close()
pool.join()