Почему записывает много NUL при записи json в многопоточности python
norm = []
erroe=[]
def threads(func, List, max_workers=20):
futures = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
for i in List:
futures.append(executor.submit(func, i))
# ждем, когда закончат выполняться задачи
list_res = []
for future in futures:
list_res.append(future.result())
return(list_res)
Используя эту функцию пытаюсь записывать картинки в base64 в json file. Просматривая полученный файл вижу в разных местах много NUL. Хочу понять почему так и как это исправить. При чем копирую этот символ вставляю в код и он просто как один пробел. Предполагаю что это может быть из-за того что несколько потоков пытаются перезаписать один и тот же файл одновременно, хотя тогда бы он наверно вообще не открылся или был бы конфликт.
def read_j(file_name, encod='utf8'):
with open(file_name, 'r', encoding=encod) as f:
F = json.load(f)
return F
def write_j(data, file_name, type='w', indent=4, ensure_ascii=False, encod='utf8'):
with open(file_name, type, encoding=encod) as f:
json.dump(data, f, indent=indent, ensure_ascii=ensure_ascii)
def url_to_b64(link_to_file, file_name=None):
# скачивает файл по ссылке и записывает его в виде base64
fileB64 = base64.b64encode(requests.get(link_to_file).content).decode('utf8')
if file_name == None:
return fileB64
else:
write_f(fileB64, file_name)
def func(art):
start = time.time()
if art not in downloaded:
try:
try:
page = requests.get('https://сайт' + art + '&locale=ru_RU',
timeout=31).content
except:
page = requests.get('https://сайт' + art + '&locale=ru_RU',
timeout=25).content
pics = bs(page, features='html.parser', from_encoding="iso-8859-1").find_all('figure', class_="ds-overview-image")
if pics != []:
new_pics = []
for element in pics:
pic = element.find('a').get('href')
new_pics.append(pic)
pics = new_pics
new_pics = []
else:
pics = bs(page, features='html.parser', from_encoding="iso-8859-1").find('div',
class_='col-xs-12 col-md-4 ds-overview-product-image').find(
'a').get('href')
pics = [pics]
pics_b64 = []
for pic in pics:
b64_pic = pomo.url_to_b64(pic)
pics_b64.append(b64_pic)
time.sleep(0.1)
d = {art: [pics, pics_b64]}
norm.append(d)
# print(pic)
pomo.write_j(data=norm, file_name='PICS_THIRD.json')
print(art, "успешный успех")
except:
# print(traceback.format_exc())
error.append(art)
write_j(error, 'error_of_getting_pics_SECOND.json')
print(art, "это фиаско брат")
now_time = time.time() - start
print('sec', now_time)
threads(func, articls_from_prices, 60)
Ответы (1 шт):
Автор решения: Roman Konoval
→ Ссылка
Тут можно не заморачиваться со списком norm его синхронизацией и т.д. У вас сама функция парсинга func может возвращать результат и основной поток будет собирать все и записывать:
def func(art):
...
# вместо
# norm.append(d)
# pomo.write_j(data=norm, file_name='PICS_THIRD.json')
# возвращаем результат
return d
def threads(func, List, max_workers=20):
futures = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
for i in List:
futures.append(executor.submit(func, i))
# ждем, когда закончат выполняться задачи
list_res = []
for future in futures:
list_res.append(future.result())
# записываем один раз, но можно и после каждого результата в предыдущем цикле
pomo.write_j(data=list_res, file_name='PICS_THIRD.json')

