Получать файлы картинок с темами и очередями на конкретном сайте - PullRequest
0 голосов
/ 08 июня 2019

Я пытаюсь создать простую программу на python3 с потоками и очередью для одновременной загрузки изображений из URL-ссылок, используя 4 или более потоков, для одновременной загрузки 4 изображений и загрузки указанных изображений в папку загрузок на ПК.избегая дублирования, разделяя информацию между потоками.Я полагаю, я мог бы использовать что-то вроде URL1 = «Link1»?Вот несколько примеров ссылок:

«https://unab -dw2018.s3.amazonaws.com / ldp2019 / 1.jpeg »

«https://unab -dw2018.s3.amazonaws.com / ldp2019 / 2.jpeg

Но я не понимаю, как использовать потоки с очередью, и я теряюсь, как это сделать.

Я попытался найти страницу, которая может объяснить, как использовать потоки с очередью для одновременной загрузки. Я нашел ссылки только для потоков.

Вот код, который работает частично.Что мне нужно, так это чтобы программа спросила, сколько потоков вы хотите, и затем загрузите изображения, пока они не достигнут изображения 20, но в коде, если ввод 5, будет загружено только 5 изображений и так далее.Дело в том, что если я поставлю 5, он сначала загрузит 5 изображений, затем следующие 5 и так далее до 20. Если его 4 изображения, то 4, 4, 4, 4, 4. Если его 6, то он пойдет 6,6,6, а затем загрузите оставшиеся 2. Каким-то образом я должен реализовать очередь в коде, но я просто изучил потоки несколько дней назад, и я забыл о том, как смешивать потоки и очередь вместе.

import threading
import urllib.request
import queue # i need to use this somehow


def worker(cont):
    print("The worker is ON",cont)
    image_download = "URL"+str(cont)+".jpeg"
    download = urllib.request.urlopen(image_download)
    file_save = open("Image "+str(cont)+".jpeg", "wb")
    file_save.write(download.read())
    file_save.close()
    return cont+1


threads = []
q_threads = int(input("Choose input amount of threads between 4 and 20"))
for i in range(0, q_threads):
    h = threading.Thread(target=worker, args=(i+1, int))
    threads.append(h)
for i in range(0, q_threads):
    threads[i].start()

1 Ответ

1 голос
/ 08 июня 2019

Я адаптировал следующее из некоторого кода, который использовал для выполнения многопоточного PSO

import threading
import queue

if __name__ == "__main__":
    picture_queue = queue.Queue(maxsize=0)
    picture_threads = []
    picture_urls = ["string.com","string2.com"]

    # create and start the threads
    for url in picture_urls:
        picture_threads.append(picture_getter(url, picture_queue))
        picture_threads[i].start()

    # wait for threads to finish
    for picture_thread in picture_threads:
        picture_thread.join()

    # get the results
    picture_list = []
    while not picture_queue.empty():
        picture_list.append(picture_queue.get())

class picture_getter(threading.Thread):
    def __init__(self, url, picture_queue):
        self.url = url
        self.picture_queue = picture_queue
        super(picture_getter, self).__init__()

    def run(self):
        print("Starting download on " + str(self.url))
        self._get_picture()

    def _get_picture(self):
        # --- get your picture --- #
        self.picture_queue.put(picture)

Как вы знаете, люди в stackoverflow любят сначала посмотреть, что вы пробовали, прежде чем предлагать решение.Однако у меня этот код все равно лежит.Добро пожаловать на борт новичка!

Одна вещь, которую я добавлю, заключается в том, что это не позволяет избежать дублирования при обмене информацией между потоками.Это позволяет избежать дублирования, поскольку каждому потоку сообщается, что загружать.Если ваши имена файлов нумеруются так, как они, кажется, в вашем вопросе, это не должно быть проблемой, так как вы можете легко составить список из них.

Обновлен код для исправления изменений в оригинальной записи Treyons

import threading
import urllib.request
import queue
import time

class picture_getter(threading.Thread):
    def __init__(self, url, file_name, picture_queue):
        self.url = url
        self.file_name = file_name
        self.picture_queue = picture_queue

        super(picture_getter, self).__init__()

    def run(self):
        print("Starting download on " + str(self.url))
        self._get_picture()

    def _get_picture(self):
        print("{}: Simulating delay".format(self.file_name))
        time.sleep(1)

        # download and save image
        download = urllib.request.urlopen(self.url)
        file_save = open("Image " + self.file_name, "wb")
        file_save.write(download.read())
        file_save.close()
        self.picture_queue.put("Image " + self.file_name)

def remainder_or_max_threads(num_pictures, num_threads, iterations):
    # remaining pictures
    remainder = num_pictures - (num_threads * iterations)

    # if there are equal or more pictures remaining than max threads
    # return max threads, otherwise remaining number of pictures
    if remainder >= num_threads:
        return max_threads

    else:
        return remainder

if __name__ == "__main__":
    # store the response from the threads
    picture_queue = queue.Queue(maxsize=0)
    picture_threads = []
    num_pictures = 20

    url_prefix = "https://unab-dw2018.s3.amazonaws.com/ldp2019/"
    picture_names = ["{}.jpeg".format(i+1) for i in range(num_pictures)]

    max_threads = int(input("Choose input amount of threads between 4 and 20: "))

    iterations = 0

    # during the majority of runtime iterations * max threads is 
    # the number of pictures that have been downloaded
    # when it exceeds num_pictures all pictures have been downloaded
    while iterations * max_threads < num_pictures:
        # this returns max_threads if there are max_threads or more pictures left to download
        # else it will return the number of remaining pictures
        threads = remainder_or_max_threads(num_pictures, max_threads, iterations)

        # loop through the next section of pictures, create and start their threads
        for name, i in zip(picture_names[iterations * max_threads:], range(threads)):
            picture_threads.append(picture_getter(url_prefix + name, name, picture_queue))
            picture_threads[i + iterations * max_threads].start()

        # wait for threads to finish
        for picture_thread in picture_threads:
            picture_thread.join()

        # increment the iterations
        iterations += 1

    # get the results
    picture_list = []
    while not picture_queue.empty():
        picture_list.append(picture_queue.get())

    print("Successfully downloaded")
    print(picture_list)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...