Python版本:3.6
操作系统:Windows 10
我想使函数执行与多个参数并行。因此,我将multiprocessing
对象Pool
与map
方法一起使用。由于每个函数调用都会持续几个小时,因此我想使用tqdm
进度条来跟踪进度。
因此,我尝试了以下代码:
from datetime import date, timedelta
from multiprocessing.pool import Pool
from tqdm import tqdm
def some_func(date1):
for i in range(1000000):
pass
def load_data(date1, n_process):
dLength = 100
progressbar = tqdm(range(0, dLength), position=n_process)
for i in range(dLength):
some_func(date1)
progressbar.update(i)
if __name__ == '__main__':
d1 = date(2018, 5, 22)
d2 = date(2018, 5, 26)
delta = d2 - d1
dates_range = []
for i in range(delta.days + 1):
date1 = d1 + timedelta(i)
dates_range.append(date1)
n_processes = 5
with Pool(n_processes) as p:
p.starmap(load_data, zip(dates_range, range(n_processes)))
问题是进度条开始重复并且不便于跟踪:
0%| | 0/101373 [00:00
0%| | 0/101373 [00:05
0%| | 1/101373 [00:09 <128:35:56,4.57s / it] 0%| | 0/217102 [00:01
0%| | 0/214016 [00:00
0%| | 3/101373 [00:11 <97:28:47,3.46s / it]
0%| | 0/214016 [00:01
0%| | 6/101373 [00:12 <72:00:37,2.56s / it] 0%| | 1/217102 [00:03 <81:07:30,1.35s / it]
0%| | 1/214016 [00:02 <66:16:01,1.11s / it] 0%| | 3/217102 [00:04 <66:47:19,1.11s / it]
我如何将文本转换为如下形式:
0%| | 0/101373 [00:00
0%| | 0/101373 [00:05
0%| | 0/217102 [00:00
0%| | 0/101373 [00:09 <128:35:56,4.57s / it]
0%| | 0/217102 [00:01
然后,在同一行中:
0%| | 1/101373 [00:00
0%| | 5/101373 [00:05
0%| | 20/217102 [00:00
0%| | 15/101373 [00:09 <128:35:56,4.57s / it]
0%| | 30/217102 [00:01
,依此类推...?
答案 0 :(得分:0)
我也有同样的问题。我确定要显示每个进程的进度条以及一个指示整个进度的进度条,并保留一个额外的进程来维护所有进度条。 multiprocessing.Manager().Queue()
用于进程之间的通信(以创建,更新和关闭进度条)。这是我的测试代码。
import multiprocessing
from time import sleep
from tqdm import tqdm
def maintain_pbar(queue, num_of_tasks):
"""
{
"id": taskid,
"cmd": "create", "update", "terminate" or "finish"
"data": int, parameters for cmd
"message": string for updating the description of tqdm progress bar
}
"""
pbars = dict()
overall_pbar = tqdm(total=num_of_tasks, ncols=80, desc="Total progress")
while True:
message = queue.get(True)
if message["cmd"] == "create":
pbars[str(message["id"])] = tqdm(total=message["data"],
ncols=80,
desc="Task #" + str(message["id"]) + message["message"])
elif message["cmd"] == "update":
pbars[str(message["id"])].update(message["data"])
elif message["cmd"] == "terminate":
pbars[str(message["id"])].close()
overall_pbar.update()
elif message["cmd"] == "finish":
overall_pbar.close()
break
def progresser(params):
n = params[0]
queue = params[1]
interval = 0.01 / (n + 2)
total = 5000
queue.put({"id": n, "cmd": "create", "data": total, "message": ""})
for _ in range(total):
sleep(interval)
queue.put({"id": n, "cmd":"update", "data": 1, "message":""})
queue.put({"id": n, "cmd": "terminate", "data": 1, "message": ""})
if __name__ == '__main__':
pool = multiprocessing.Pool(4)
queue = multiprocessing.Manager().Queue()
l = [(i, queue) for i in range(20)]
pool.apply_async(maintain_pbar, (queue, len(l)))
pool.map(progresser, l)
queue.put({"cmd": "finish"})
pool.close()
pool.join()
希望这会有所帮助!