Многопоточная очистка веб-страниц в Python / PySide / PyQt - PullRequest
2 голосов
/ 12 марта 2012

Я строю своего рода веб-скребок. В основном то, что сделал бы софт, это:

  1. Пользователь (я) вводит некоторые данные (идентификаторы) - идентификаторы являются сложными, поэтому не просто цифры
  2. На основании этих идентификаторов скрипт посещает http://localhost/ID

Каков наилучший способ сделать это? Поэтому я смотрю на 20-30 одновременных соединений, чтобы сделать это.

Я думал, будет ли простой цикл решением проблемы? Этот цикл запускает QThreads (это приложение Qt), поэтому они запускаются одновременно.

Однако проблема, с которой я сталкиваюсь в цикле, заключается в том, как заставить его использовать только те идентификаторы, которые не использовались до этого, т. Е. В итерации / потоке, которые были выполнены незадолго до этого? Нужна ли мне какая-то функция «делегатора», которая будет отслеживать, какие идентификаторы были использованы, и делегировать неиспользуемые идентификаторы в QThreads?

Теперь я написал некоторый код, но я не уверен, что он правильный:

class GUI(QObject):

   def __init__(self):
        print "GUI CLASS INITIALIZED!!!"
        self.worker = Worker()

        for i in xrange(300):
            QThreadPool().globalInstance().start(self.worker)

class Worker(QRunnable):

    def run(self):
        print "Hello world from thread", QThread.currentThread()

Теперь я не уверен, действительно ли они достигают того, чего я хочу. Это на самом деле работает в отдельных потоках? Я спрашиваю, потому что currentThread() одинаково каждый раз, когда выполняется, так что это не выглядит так.

По сути, мой вопрос сводится к тому, как одновременно выполнить несколько одинаковых QThreads?

Заранее спасибо за ответ!

1 Ответ

5 голосов
/ 12 марта 2012

Как говорит Дикеи, Qt здесь красная сельдь.Сосредоточьтесь на том, чтобы просто использовать потоки Python, поскольку это сделает ваш код намного проще.

В приведенном ниже коде у нас есть набор job_queue, содержащий задания, которые должны быть выполнены.У нас также есть функция worker_thread, которая берет задание из переданной очереди и выполняет его.Здесь он просто спит в течение случайного периода времени.Ключевым моментом здесь является то, что set.pop является потокобезопасным.

Мы создаем массив объектов потока, workers, и вызываем start для каждого при его создании.Из документации Python threading.Thread.start запускает данный вызываемый объект в отдельном потоке управления.Наконец, мы проходим каждый рабочий поток и блокируем его до тех пор, пока он не завершится.

import threading
import random
import time

pool_size = 5

job_queue = set(range(100))

def worker_thread(queue):
   while True:
        try:
            job = queue.pop()
        except KeyError:
            break

        print "Processing %i..." % (job, )
        time.sleep(random.random())

    print "Thread exiting."

workers = []
for thread in range(pool_size):
    workers.append(threading.Thread(target=worker_thread, args=(job_queue, )))
    workers[-1].start()

for worker in workers:
    worker.join()

print "All threads exited"
...