Не пренебрегайте полезностью пулов, особенно если вы хотите контролировать количество создаваемых процессов.Они также заботятся о том, чтобы управлять вашими работниками (создавать / запускать / объединять / распределять куски работы) и помогать вам собирать потенциальные результаты.
Как вы сами осознали, вы создаете слишком много процессов, вплоть до определенного момента.где вы, кажется, исчерпали столько системных ресурсов, что не можете создавать больше процессов.
Кроме того, создание новых процессов в вашем коде контролируется внешними факторами, то есть количеством папок в ваших файловых деревьях, что очень затрудняет ограничение количества процессов.Кроме того, создание нового процесса сопряжено с некоторыми накладными расходами в ОС, и вы можете даже потратить эти накладные расходы на пустые каталоги.Кроме того, переключение контекста между процессами является довольно дорогостоящим.
Учитывая количество создаваемых вами процессов и указанное вами количество папок, ваши процессы в основном будут просто сидеть и простаивать большую часть времени, пока они ждутдоля процессорного времени, чтобы фактически сделать некоторую работу.За указанное процессорное время будет много споров, если только в вашем распоряжении не будет суперкомпьютер с тысячами ядер.И даже когда процесс получает некоторое время процессора, он, скорее всего, потратит немало времени на ожидание операций ввода-вывода.
При этом вы, вероятно, захотите изучить использование потоков для такой задачи.И вы могли бы сделать некоторую оптимизацию в вашем коде.Из вашего примера я не вижу причин, по которым вы бы разделили идентифицирующие файлы для копирования и фактически копировали их в разные задачи.Почему бы не позволить вашим работникам сразу скопировать каждый найденный файл, соответствующий RE?
Я бы создал список файлов в рассматриваемых каталогах, используя os.walk
(который я считаю разумнымбыстро) из основного потока, а затем выгрузить этот список в пул рабочих, который проверяет эти файлы на наличие совпадений и сразу же копирует их:
import os
import re
from multiprocessing.pool import ThreadPool
search_dirs = ["dir 1", "dir2"]
ptn = re.compile(r"your regex")
# your target dir definition
file_list = []
for topdir in search_dirs:
for root, dirs, files in os.walk(topdir):
for file in files:
file_list.append(os.path.join(root, file))
def copier(path):
if ptn.match(path):
# do your shutil.copyfile with the try-except right here
# obviously I did not want to start mindlessly copying around files on my box :)
return path
with ThreadPool(processes=10) as pool:
results = pool.map(copier, file_list)
# print all the processed files. For those that did not match, None is returned
print("\n".join([r for r in results if r]))
С другой стороны: не объединяйте пути вручную (file[0] + "\\" + file[1]
), для этого лучше использовать os.path.join
.