Python—如何按执行顺序将具有共享结果的独特函数并行化?

Python—如何按执行顺序将具有共享结果的独特函数并行化?,python,multithreading,concurrency,python-requests,threadpool,Python,Multithreading,Concurrency,Python Requests,Threadpool,每个函数func1等向不同的url发出请求: def thread_map(ID): func_switch = \ { 0: func1, 1: func2, 2: func3, 3: func4 } with ThreadPoolExecutor(max_workers=len(func_switch)) as threads: f

每个函数func1等向不同的url发出请求:

def thread_map(ID):
    func_switch = \
        {
            0: func1,
            1: func2,
            2: func3,
            3: func4
        }

    with ThreadPoolExecutor(max_workers=len(func_switch)) as threads:
        futures = [threads.submit(func_switch[i], ID) for i in func_switch]
        results = [f.result() for f in as_completed(futures)]

        for df in results:
            if not df.empty and df['x'][0] != '':
                return df

        return pd.DataFrame()
这比for循环快了1.75秒,但结果是无序的

在允许按执行顺序检查结果的同时,如何并行执行每个函数? 最好作为后台进程/线程返回从func1开始的相应数据帧。因此,如果不满足func1的条件,请检查func2等条件,以了解已在后台获取结果的条件。每个数据帧都不同,但它们都包含相同的公共列x


非常感谢您的建议,我希望ThreadPoolExecutor适合此场景。谢谢

首先,让我们按照你的要求做:

with ThreadPoolExecutor(max_workers=len(func_switch)) as threads:
    futures = [threads.submit(func_switch[i], ID) for i in func_switch]
results = [f.result() for f in futures]
这很简单

要在期货完成时对其进行处理,并将结果放入创建期货的列表中,您需要按照创建期货的顺序与每个期货关联:

futures = {} # this time a dictionary
creation_order = 0
with ThreadPoolExecutor(max_workers=len(func_switch)) as threads:
    for i in func_switch:
        future = threads.submit(func_switch[i], ID)
        futures[future] = creation_order # map the future to this value or any other values you want, such as the arguments being passed to the function, which happens to be the creation order
        creation_order += 1
results = [None] * creation_order # preallocate results
for f in as_completed(futures):
    result = f.result()
    index = futures[f] # recover original creation_order:
    results[index] = result

当然,如果你在做任何事情之前等待所有的未来完成,那么使用as_completed方法是没有意义的。我只是想说明如果不是这样的话,如何将已完成的未来与原始创建顺序或可能更有用的原始参数(在调用创建未来的worker函数时使用的原始参数)关联起来。另一种方法是处理函数将传递的参数作为结果的一部分。

可以使用返回的顺序,而不是完成的顺序。@ DARRYLG我认为MAP方法有两个问题。第一个,虽然是次要的,但是如果被调用的函数采用的不是一个参数,那么您需要使用lambda函数或partial函数之类的函数。第二种情况是,如果任何线程抛出异常,那么一旦从抛出异常的线程检索到结果,您将无法获得任何后续线程的结果。Thank you@Booboo就像一个符咒,结果是有序的+1因为预分配是有意义的,现在我能更好地遵循你的代码了,我以前一定有过精神错乱。我仍然不知道为什么func_开关不是一个简单的列表,而不是一个字典。