Как запускать определенное кол-во потоков?
Имею файл в 10к записей. Как запускать 10 потоков для каждые 10 записей. То есть, чтоб было не больше 10 потоков.
Имею такой код:
from threading import Thread
from openpyxl import load_workbook, Workbook
from fuzzywuzzy import process
def get_list_data(input_file_name):
'''Получение списка товаров из файла'''
list_data = []
wb = load_workbook(filename=input_file_name)
sheet = wb.active
m_row = sheet.max_row
with open('conf/alias.txt', 'r') as file_alias:
list_alias = []
for item in file_alias:
# if ',' in item:
# list_alias.append(item.title().replace(
# '\n', '').split(',')[-1])
# else:
list_alias.append(item.title().replace('\n', ''))
for i in range(1, m_row+1):
if not sheet.cell(row=i, column=1).value:
continue
title = str(sheet.cell(row=i, column=1).value).replace("'", '')
brand_s = str(sheet.cell(row=i, column=2).value).replace(
"'", '').rstrip().title().split(' ')
point_match = process.extractOne(brand_s[0], list_alias)
alias = str(sheet.cell(row=i, column=2).value).replace("'", '').rstrip().title()
if point_match is not None:
if point_match[-1] >= 50:
alias = point_match[0]
brand = '+'.join(brand_s)
min_count = str(sheet.cell(row=i, column=3).value).replace("'", '')
max_time_delivery = str(sheet.cell(
row=i, column=4).value).replace("'", '')
count_sell = str(sheet.cell(
row=i, column=5).value).replace("'", '')
object = {'idnp': title, 'brand': brand, 'min_count': min_count,
'max_time_delivery': max_time_delivery, 'count_sell': count_sell, 'alias': alias}
list_data.append(object)
return list_data
if __name__ == '__main__':
list_data = get_list_data('Копия китай.xlsx')
for index,item in enumerate(list_data):
print(index)
Была идея сделать так: запустить цикл по списку с шагом 10 и создавать поток на i,i-1,i-2,...,i-10 записей. Но с enumerate такое сделать не получается. Была еще идея: добавлять в список индексы записей уже которые были в потоках и каждый раз проверять, но это слишком тупо. Подскажите как сделать правильно.
Вот ссылка на исходник: https://cloud.mail.ru/public/572o/pU2nd1a5M
А что должно получится это не имеет значения, просто мне нужно понять как эти 10 потоков запустить
Ответы (1 шт):
Возможно, вам и не нужны потоки. Я вижу как минимум две возможности ускорить этот код:
- Вынести чтение и парсинг файла 'conf/alias.txt' из функции. Он у вас вроде нигде не меняется в процессе работы программы. Читайте файл заранее и передавайте в функцию
get_list_dataготовый список псевдонимов. - Использовать по мере возможности кэширование, чтобы не дёргать насколько я понимаю весьма затратную по времени функцию
fuzzywuzzy.process.extractOne.
Примерно так:
from functools import lru_cache
@lru_cache
def extract_one(name):
process.extractOne(name, list_alias)
# ...
point_match = extract_one(brand_s[0])
Конечно, тут надо list_alias сформировать сразу и сделать доступным глобально. Можно его и в качестве аргумента функции extract_one передавать, но лучше не надо, чтобы не загружать кэш лишней информацией и проверками.
В принципе, можно и ещё какие-то куски кода вынести в кэширующие декораторы, но это надо ещё думать. Если у вас часто повторяются одни и те же строки в brand_s[0] ускорение при таком кэшировании должно быть весьма неплохим.
Но если захотите всё же использовать потоки, то проще всего использовать Pool из модуля multiprocessing, там всё просто. Пример из документации:
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
p = Pool(5)
print(p.map(f, [1, 2, 3]))