python爬虫多线程之queue

本文深入探讨了队列在多线程编程中的应用,通过实例展示了如何利用队列进行任务分配与管理,实现高效并行处理。通过简单的代码示例,清晰地介绍了队列的基本方法及其实现过程,最终通过多线程执行验证了队列在任务调度上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        首先先来介绍下queue这个包吧,这个包叫队列,没错,就是那个和栈反过来的那个队列,大家一听队列就随口说出先进先出,而栈则是后进先出,为什么要用用队列来实现,其实我也不知道,反正用过之后很顺手,具体哪里也说不上来

        先来看下队列的内置方法的,我们只需要记住两个,一个是put 放 ,另一个是get 获得,因为我们q = queue.Queue()创建了一个队列后,这个队列是空的,要先放东西进去才能从里面拿东西出来

q = queue.Queue()    
q.qsize()           返回队列的大小  
q.empty()         如果队列为空,返回True,反之False  
q.full()          如果队列满了,返回True,反之False 
q.full              与 maxsize 大小对应  
q.get([block[, timeout]]) 获取队列,timeout等待时间  
q.get_nowait()         相当q.get(False) 
q.put(item)           写入队列,timeout等待时间  
q.put_nowait(item)    相当q.put(item, False) 
q.task_done()         在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号 
q.join()             实际上意味着等到队列为空,再执行别的操作

下面是我自己写的一个简单的代码,我会用文字来注释,以便大家能看懂,真心简单,熟悉读完这篇文章后你如果还不会的话,那我也没什么说的了

#开启多个线程,同时执行任务,有几个线程就执行几个任务

import threading
import time
import queue

class MyThread(threading.Thread):
    def __init__(self, func):
        threading.Thread.__init__(self)
        self.func = func
    def run(self):
        self.func()

def worker():
    while not q.empty():
        item = q.get()  # 或得任务
        print('Processing : ',item)
        time.sleep(1)

def main():
    threads = []
    for task in range(100):
        q.put(task)
    for i in range(threadNum):   #开启三个线程
        thread = MyThread(worker)
        thread.start()
        threads.append(thread)
    for thread in threads:
        thread.join()

if __name__ == '__main__':
    q = queue.Queue()
    threadNum = 3
    main()

看代码先看主入口,根据里面的函数调用一步步来

1.    首先我实例化了一个队列  q = queue.Queue()    ,然后我设置线程数为3,接着调用main() 方法

2.    进入main函数中,我创建了一个空列表,用来放线程,第一个for 循环中我做的是将(0,100)之间数据放入队列当中,当然,100是取不到的,放完队列后又来了个for循环,这个for循环是用来创建线程的,前面说了threadNum = 3,那么说明我这里要循环三次,threadNum的值分别为0,1,2,当然,这三个数用不到,因为我没在MyThread写线程名,没有把thread作为参数传入类中,所以每个线程都是无名氏,我们看到thread = MyThread(worker) 这段代码,先来看MyThread这个类,worker这个参数先不看,MyThread中这个类继承了threading.Thread,在init方法中初始化了父类,也就是threading.Thread,并且定义了一个属性,属性名叫func,因为threading这个类有自己的run方法,我们可以重写父类的run方法,self.func()  表明但我们start后,线程会自动调用run方法,就会执行self.func() 这句

3.     看完MyThread这个类后我们就来看worker这个参数,有的人就会问,看了半天没看到有这个参数啊,谁说参数一定是变量啊,也有可能是函数啊,现在就有人恍然大悟了,看到worker这个方法。这个方法里面一个while循环,我使用的一个队列的方法,这个方法是q.empty(),这个方法说明当队列q为空时,他的值为True,前面写了个not ,说明整句的意思是,当队列q不为空时才会执行这个while循环。一开始定义一个变量item 来接收得到的数据,打印一遍并且休眠一秒,不休眠的话程序运行太快,看不到多线程的效果,以上  thread = MyThread(worker)  这句代码就解释完了

4.     thread.start() 这句是启动线程,threads.append(thread)是将线程加入到前面定义的threads空列表中,最后这个for循环是将每个线程都join()一下,join的意思是等线程结束后才会执行后面的语句,我们这里的意思是前面三个线程跑完了才能轮到后面三个线程

5.    基本的代码都讲解完毕了,现在来运行代码

就会发现,一次输出三句,停顿一秒后又输出三句,因为开了三个线程,有兴趣的可以把我代码复制下来并且将线程数改下来看下效果,看到这估计有人就明白了,这个queue队列相当于或类似一个全局的列表,只负责存和取,没错,他的作用就是这样,最起码我用的只有这么多

下面还有一个列子,这个列子是我想执行一个永不停止的线程,每次队列被取完后,我都会将数据原样放回去,具体的步骤我就不说了,上面有写

import threading
import queue
import time

class Mythread(threading.Thread):
    def __init__(self,fun):
        threading.Thread.__init__(self)
        self.fun = fun
    def run(self):
        self.fun()

def worker():
    global data
    while True:
        if not q.empty():
            a = q.get()
            parse(a[0], a[1])
            time.sleep(1)
            data.append(a)
        else:
            for i in data:
                q.put(i)
            data = []


def parse(qd, zd):
    mystr = qd + zd
    print('=============',mystr)

def main():
    threads = []
    for i in LstAdd:
        q.put(i)
    for i in range(thendNum):
        thread = Mythread(worker)
        thread.start()
        threads.append(thread)
    for thread in threads:
        thread.join()

if __name__ == '__main__':
    LstAdd = [
        ('abcde1','adfa1'),
        ('abcde2','adfa2'),
        ('abcde3','adfa3'),
        ('abcde4','adfa4'),
        ('abcde5','adfa5'),
        ('abcde6','adfa6'),
        ('abcde7','adfa7'),
        ('abcde8','adfa8'),
        ('abcde9','adfa9'),
              ]
    data = []
    q = queue.Queue()
    thendNum = 3
    main()

我想将列表中每个元素即元组的两个元素相加并输出,运行程序结果如下:

他会一直输出1-9,后面的没有截图下来,太多了,我将每次get()的数据都存起来,这样防止数据丢失,每次我都会判断队列是否为空,为空的话就将存起来的数据原样存回去,并且情况存这些数据的列表,保证每次都是同样的数据同样的顺序

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值