Как получить результат потоков в том порядке, в котором они запустились?
Всех приветствую.
Немного (много) запутался в многопоточности.
Задача написать программу, которая скачает картинки с сайта.
Код следующий (некоторые места типа импортов убрал для упрощения понимания):
# Программа, которая параллельно скачивает картинки флагов
# Очередь из ссылок на картинки флагов
flag_url_queue = Queue()
# Заполняем ссылками. Кусок кода с парсингом ссылок убрал
for link in all_flag_link[:5]:
flag_url_queue.put(link)
# Главная очередь, которая должна в правильном порядке сохранять файлы
# и выводить текст об успешном скачивании картинки
main_queue = Queue()
def download_flag(url_img):
# Кусок срезаной строки использую для сохранения по имени и вывода в консоль
print(f'Начал скачивать {url_img[-10:]}')
result = requests.get(url_img)
print(f'Скачал {url_img[-10:]}')
return result, f'{url_img[-6:]}'
def save_flag(img_b, url_img):
print(f'Сохраняю флаг {url_img[-6:]}')
with open(f'./images/{url_img[-6:]}', 'wb') as img_file:
img_file.write(img_b.content)
print(f'Сохранил флаг {url_img[-6:]}')
def worker(flag_url_queue: Queue, main_queue: Queue):
while not flag_url_queue.empty():
try:
# Пытаюсь достать ссылку без блокировки потока
new_link_flag = flag_url_queue.get_nowait()
except Empty:
break
else:
# В главную очередь попадает результат функции -
# ответ requests и имя картинки
main_queue.put(download_flag(new_link_flag))
# Помечаю задачу как выполненную
flag_url_queue.task_done()
def main():
COUNT_THREAD = 4
thread_list = [threading.Thread(target=worker, args=(flag_url_queue, main_queue)) for _ in range(COUNT_THREAD)]
for thread in thread_list:
thread.start()
flag_url_queue.join()
for item in thread_list:
item.join()
while not main_queue.empty():
save_flag(*main_queue.get())
Я ожидаю, что картинки, возможно, будут скачиваться в разноброс, но в результате сохранятся в той последовательности, в которой они запустились.
Допустим, есть флаги Австралии (au.png
), Австрии (at.png
) и Азербайджана (az.png
).
При запуске получаю
Начал скачивать h80/au.png
Начал скачивать h80/at.png
Начал скачивать h80/az.png
Скачал h80/at.png <----- Скачались в другом порядке
Скачал h80/az.png
Скачал h80/au.png
Сохраняю флаг at.png <--- Начинают сохраняться в том порядке, в котором скачались, а не в изначальном
Сохранил флаг at.png
Сохранил флаг az.png
Сохранил флаг az.png
Сохраняю флаг au.png
Сохранил флаг au.png
Я жду, что они начнут скачиваться в изначальном порядке. Т.к. каждая из них весит по-разному, то я допускаю, что они загрузятся в другом порядке. Но я бы хотел, чтобы в результате они сохранялись в первоначальной очерёдности (Австралия - Австрия - Азербайджан).
Подскажите, пожалуйста, возможно ли реализовать такое с помощью threading
?
Вопрос больше для того, чтобы разобраться в теме. Проект пишется "на скорую руку" и не претендует на практическое применение.
Заранее спасибо.