Ось моя думка про те, коли вам потрібно повернути результати від ваших паралельних виконуючих функцій. Ця функція робить декілька речей (є ще одна моя публікація, яка пояснює це далі), але ключовим моментом є те, що існують завдання, які очікують на розгляд, і черга, яка завершена. Коли працівники закінчують кожне завдання в черзі, що очікує, вони додають результати в чергу, виконану із завданнями. Ви можете обернути перевірку до черги завдань, виконаної за допомогою панелі прогресу tqdm. Я не ставлю тут реалізацію функції do_work (), це не актуально, оскільки тут повідомляється про моніторинг завершеної черги завдань та оновлення індикатора виконання кожного разу, коли надходить результат.
def par_proc(job_list, num_cpus=None, verbose=False):
if not num_cpus:
num_cpus = psutil.cpu_count(logical=False)
print('* Parallel processing')
print('* Running on {} cores'.format(num_cpus))
tasks_pending = mp.Queue()
tasks_completed = mp.Queue()
processes = []
results = []
num_tasks = 0
for job in job_list:
for task in job['tasks']:
expanded_job = {}
num_tasks = num_tasks + 1
expanded_job.update({'func': pickle.dumps(job['func'])})
expanded_job.update({'task': task})
tasks_pending.put(expanded_job)
num_workers = min(num_cpus, num_tasks)
for c in range(num_workers):
tasks_pending.put(SENTINEL)
print('* Number of tasks: {}'.format(num_tasks))
for c in range(num_workers):
p = mp.Process(target=do_work, args=(tasks_pending, tasks_completed, verbose))
p.name = 'worker' + str(c)
processes.append(p)
p.start()
completed_tasks_counter = 0
with tqdm(total=num_tasks) as bar:
while completed_tasks_counter < num_tasks:
results.append(tasks_completed.get())
completed_tasks_counter = completed_tasks_counter + 1
bar.update(completed_tasks_counter)
for p in processes:
p.join()
return results