如何从ProcessPoolExecutor解包生成器结果?

2024-09-30 20:34:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用ProcessPoolExecutor来初始化一个类(BT)的多个实例,该类初始化一个方法BT.bt(),并返回结果[aList1aList2]

我尝试将类的每个实例所需的信息打包到一个简单的迭代器(bulkInfo)中。然后将迭代器抛出到类的每个实例并执行。据我所知,结果应该是一个生成器或一个列表,结果中的每个结果(combiList)都是2个“迷你列表”[aList1aList2]的列表

但是,我无法解压缩结果。或者更准确地说,我无法解压缩每个result in results。Pycharm在result[0]result[1]-Class 'BT' does not define '__getitem__', so the [] operator cannot be used on its instances突出显示警告

按原样运行代码会出现错误TypeError: 'list' object is not callable。 代码的完整版本给出了错误TypeError: cannot pickle 'generator' object

如何在results中解包每个result给我miniList1miniList2

下面的代码是一个精简版本,用于概述问题。我试过用yield代替return combiList。我尝试过将results抛出到list(results)并迭代每个结果。我尝试过将bulkinfo迭代器打包为列表列表或元组列表的许多变体。我尝试将combiList定义为列表和元组。我尝试了list(results)后跟list(result)访问每个miniList

import concurrent.futures as cf
import numpy as np

class BT:
    def __init__(self, bulkInfo):
        self.aCyc = bulkInfo(3)
        self.bt(self.aCyc)

    def bt(self, aCycle):
        aList1 = []
        aList2 = []
        someInfo = [aCycle, 'bunch', 'of', 'stuff']
        [aList1.append(s) for s in someInfo]
        [aList2.append(s) for s in someInfo]
        combiList = [aList1, aList2]
        return combiList

if __name__ == '__main__':
    dummy1 = 'something'
    cycles = np.arange(10)
    bulkInfo = []
    [bulkInfo.append([dummy1, dummy1, dummy1, aCyc]) for aCyc in cycles]

    with cf.ProcessPoolExecutor(max_workers=4) as executor:
        results = executor.map(BT, bulkInfo)

        for result in results:
            miniList1 = result[0]
            miniList2 = result[1]

        # for result in list(results):
        #     for miniList in list(result):
        #         print(miniList)

我不太关心性能,只是想从ProcessPoolExecutor中得到结果。因此,我只想将输出结果作为列表,但它可能是一个生成器(我不清楚列表何时“成为”生成器,反之亦然。我只想提取miniList1miniList2


Tags: inself列表forresultresultslistbt
1条回答
网友
1楼 · 发布于 2024-09-30 20:34:42

你的BT对象有几个问题

首先,在__init__()中,您不能使用()访问bulkInfo(这是一个列表)的元素,您需要使用括号。这就是你得到TypeError: 'list' object is not callable的原因。以下是更正的版本:

def __init__(self, bulkInfo):
    self.aCyc = bulkInfo[3]
    self.bt(self.aCyc)

其次,init方法返回一个BT对象,而不是列表列表。这就是__init__方法所做的:它创建一个对象并返回它。因此,executor.map的内容是BT对象的一个iterable。通过将combiList更改为对象的属性,可以使用result.combiList[i]访问它

当我们使用它时,您不必将self.aCyc作为bt()方法的参数传递:因为它是一个属性,所以您可以在对象方法中自由访问它

最后,您还可以直接迭代executor.map,而不需要results变量

以下是完整的工作代码:

import concurrent.futures as cf
import numpy as np

class BT:
    def __init__(self, bulkInfo):
        self.aCyc = bulkInfo[3]
        self.bt()

    def bt(self):
        aList1 = []
        aList2 = []
        someInfo = [self.aCyc, 'bunch', 'of', 'stuff']
        [aList1.append(s) for s in someInfo]
        [aList2.append(s) for s in someInfo]
        self.combiList = [aList1, aList2]

if __name__ == '__main__':
    dummy1 = 'something'
    cycles = np.arange(10)
    bulkInfo = []
    [bulkInfo.append([dummy1, dummy1, dummy1, aCyc]) for aCyc in cycles]

    with cf.ProcessPoolExecutor(max_workers=4) as executor:
        for result in executor.map(BT, bulkInfo):
            print(result.combiList)
            miniList1 = result.combiList[0]
            miniList2 = result.combiList[1]

这给了我以下输出:

[[0, 'bunch', 'of', 'stuff'], [0, 'bunch', 'of', 'stuff']]
[[1, 'bunch', 'of', 'stuff'], [1, 'bunch', 'of', 'stuff']]
[[2, 'bunch', 'of', 'stuff'], [2, 'bunch', 'of', 'stuff']]
[[3, 'bunch', 'of', 'stuff'], [3, 'bunch', 'of', 'stuff']]
[[4, 'bunch', 'of', 'stuff'], [4, 'bunch', 'of', 'stuff']]
[[5, 'bunch', 'of', 'stuff'], [5, 'bunch', 'of', 'stuff']]
[[6, 'bunch', 'of', 'stuff'], [6, 'bunch', 'of', 'stuff']]
[[7, 'bunch', 'of', 'stuff'], [7, 'bunch', 'of', 'stuff']]
[[8, 'bunch', 'of', 'stuff'], [8, 'bunch', 'of', 'stuff']]
[[9, 'bunch', 'of', 'stuff'], [9, 'bunch', 'of', 'stuff']]

相关问题 更多 >