使用tqdm与current.futures?

max*_*max 23 python concurrent.futures tqdm

我有一个多线程函数,我想要一个使用状态栏tqdm。有没有一种简单的方法可以显示状态栏ThreadPoolExecutor?正是并行化部分使我感到困惑。

import concurrent.futures

def f(x):
    return f**2

my_iter = range(1000000)

def run(f,my_iter):
    with concurrent.futures.ThreadPoolExecutor() as executor:
        function = list(executor.map(f, my_iter))
    return results

run(f, my_iter) # wrap tqdr around this function?
Run Code Online (Sandbox Code Playgroud)

Boo*_*boo 33

已接受答案的问题在于,该ThreadPoolExecutor.map函数必须生成结果,而不是按照它们可用的顺序。因此,如果第一次调用myfunc恰好是,例如,最后一次完成,进度条将同时从 0% 到 100%,并且只有当所有调用都完成时。使用ThreadPoolExecutor.submitwith会更好as_completed

import time
import concurrent.futures
from tqdm import tqdm

def f(x):
    time.sleep(0.001)  # to visualize the progress
    return x**2

def run(f, my_iter):
    l = len(my_iter)
    with tqdm(total=l) as pbar:
        # let's give it some more threads:
        with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
            futures = {executor.submit(f, arg): arg for arg in my_iter}
            results = {}
            for future in concurrent.futures.as_completed(futures):
                arg = futures[future]
                results[arg] = future.result()
                pbar.update(1)
    print(321, results[321])

my_iter = range(100000)
run(f, my_iter)
Run Code Online (Sandbox Code Playgroud)

印刷:

321 103041
Run Code Online (Sandbox Code Playgroud)

这只是一般的想法。根据 的类型my_iter,可能无法直接将 applylen函数直接应用于它而不先将其转换为列表。重点是使用submitwith as_completed

  • 由于有人刚刚问我,这里是适用于 `ProcessPoolExecutor` 的示例代码 https://gist.github.com/ltalirz/9220946c5c9fd920a1a2d81ce7375c47 (4认同)
  • 这会阻止进度条中的时间更新,有办法解决吗? (2认同)

Dat*_*yen 28

你可以用tqdm周围executor,如下跟踪进度:

list(tqdm(executor.map(f, iter), total=len(iter))

这是您的示例:

import time  
import concurrent.futures
from tqdm import tqdm

def f(x):
    time.sleep(0.001)  # to visualize the progress
    return x**2

def run(f, my_iter):
    with concurrent.futures.ThreadPoolExecutor() as executor:
        results = list(tqdm(executor.map(f, my_iter), total=len(my_iter)))
    return results

my_iter = range(100000)
run(f, my_iter)
Run Code Online (Sandbox Code Playgroud)

结果是这样的:

16%|???           | 15707/100000 [00:00<00:02, 31312.54it/s]
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你!关键似乎是tqdm周围的list(),为什么会这样呢? (2认同)
  • @DreamFlasher:这种行为是因为 tqdm 在执行时运行。Executor.map 本身只是一个生成器。 (2认同)
  • 这样,你不会立即得到输出!所以你必须等到全部进度完成才能看到完整的结果! (2认同)

use*_*257 6

我认为最短的方法是:

with ThreadPoolExecutor(max_workers=20) as executor:
    results = list(tqdm(executor.map(myfunc, range(len(my_array))), total=len(my_array)))
Run Code Online (Sandbox Code Playgroud)