Python / PySide / PyQt中的多线程Web抓取

时间:2012-03-12 14:50:39

标签: python multithreading pyqt pyside

我正在建立一种网络刮刀。基本上,软会做的是:

  1. 用户(我)输入一些数据(ID) - ID很复杂,所以不仅仅是数字
  2. 根据这些ID,脚本会访问http://localhost/ID
  3. 实现这一目标的最佳方法是什么?所以我正在寻找20-30个并发连接来实现它。

    我在想,一个简单的循环会成为解决方案吗?这个循环会启动QThreads(它是一个Qt应用程序),所以它们会同时运行。

    我在循环中看到的问题是如何指示它只使用之前未使用的那些ID,即在之前执行的迭代/线程中?我是否需要某种“委托”功能来跟踪已使用的ID并将未使用的ID委托给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 个答案:

答案 0 :(得分:5)

正如Dikei所说,Qt在这里是红鲱鱼。专注于使用Python线程,因为它将使您的代码更加简单。

在下面的代码中,我们有一个集合job_queue,其中包含要执行的作业。我们还有一个函数worker_thread,它从传入的队列中获取作业并执行。在这里,它只是随机休息一段时间。这里的关键是set.pop是线程安全的。

我们创建一个线程对象数组workers,并在每个对象上调用start。从Python documentation threading.Thread.start在一个单独的控制线程中运行给定的callable。最后,我们遍历每个工作线程并阻塞,直到它退出。

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"