通过线程池调用成员函数时缺少必需的位置参数

时间:2017-07-05 19:53:45

标签: python multithreading threadpoolexecutor

我编写了以下两种方法,试图从多线程中受益:

class Data:

    def read_single_image(self, resample_size, index, image_directory_path):
        file_name = self.file_names[index]
        file_path = os.path.join(image_directory_path, file_name + '.*')
        files = glob.glob(file_path)
        if len(files) != 1:
            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), file_path)
        image = misc.imread(file_path, mode='RGB')
        zoom = image.shape
        # image = interpolation.zoom(image_directory_path)
        zoom = (resample_size[0] / zoom[0], resample_size[1] / zoom[1], 1)
        image = interpolation.zoom(image, zoom)
        return image


    def read_images(self, resample_size, indice=None, image_directory_path=train_jpeg_directory_path):

        if indice is None:
            indice = self.shuffled_indice

        # reading all images into list
        images = []
        # for i in indice:
        #     image = self.read_single_image(resample_size, i, image_directory_path)
        #     images.append(image)
        with ThreadPoolExecutor(cpu_count()) as pool:
            for image in pool.map(self.read_single_image, [(resample_size, i, image_directory_path) for i in indice]):
                images.append(image)

        return np.stack(images)

不幸的是,它不适用于错误消息:

TypeError: read_single_image() missing 2 required positional arguments: 'index' and 'image_directory_path'

为什么?

1 个答案:

答案 0 :(得分:1)

Executor.map()(因此ThreadPoolExecutor.map())获取一个iterable,并通过封闭池将其发送给每个worker一个项目。这意味着您的Data.read_single_image()方法被调用为:self.read_single_image((resample_size, i, image_directory_path))即获取所有参数的tuple作为第一个参数(在隐含的self之后),因此它会抱怨它没有收到最后两个位置参数。

您只需将Data.read_single_image()签名更改为:Data.read_single_image(self, args),然后从args元组resample_size读取为args[0],{{1 } indexargs[1]image_directory_path

如果要保留签名,可以将代理扩展器编写为:

args[2]

然后从def _read_single_image(self, args): return self.read_single_image(*args) 调用_read_single_image()方法(即ThreadPoolExecutor.map()

请注意,如果您要进行一些严肃的处理,那么使用pool.map(self._read_single_image, [(resample_size, i, image_directory_path) for i in indice])模块会更好,multiprocessing仍然受到可怕的GIL的限制