我遇到了以下问题。我正在尝试重构我的代码,以便使用多线程处理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
答案 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()