zoukankan      html  css  js  c++  java
  • python Queue模块使用

    Python中,队列是线程间最常用的交换数据的形式。Queue模块是提供队列操作的模块,虽然简单易用,但是不小心的话,还是会出现一些意外。

    创建一个“队列”对象
    import Queue
    q = Queue.Queue(maxsize = 10)
    Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

    将一个值放入队列中
    q.put(10)    put(item[, block[, timeout]])

    将item放入队列中。

    1. 如果可选的参数block为True且timeout为空对象(默认的情况,阻塞调用,无超时)。
    2. 如果timeout是个正整数,阻塞调用进程最多timeout秒,如果一直无空空间可用,抛出Full异常(带超时的阻塞调用)。
    3. 如果block为False,如果有空闲空间可用将数据放入队列,否则立即抛出Full异常

    其非阻塞版本为put_nowait等同于put(item, False)

    将一个值从队列中取出
    q.get()    get([block[, timeout]])

    调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。

    从队列中移除并返回一个数据。block跟timeout参数同put方法

    其非阻塞方法为`get_nowait()`相当与get(False)

    Python Queue模块有三种队列及构造函数:
    1、Python Queue模块的FIFO队列先进先出。     class Queue.Queue(maxsize)
    2、LIFO类似于堆,即先进后出。                         class Queue.LifoQueue(maxsize)
    3、还有一种是优先级队列级别越低越先出来。    class Queue.PriorityQueue(maxsize)

    此包中的常用方法(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() 在完成一项工作之后,向任务已经完成的队列发送一个信号,每一个get()调用得到一个任务,接下来的task_done()调用告诉队列该任务已经处理完毕。如果当前一个join()正在阻塞,它将在队列中的所有任务都处理完时恢复执行(即每一个由put()调用入队的任务都有一个对应的task_done()调用)。

    q.join() 实际上意味着等到队列为空,再执行别的操作.阻塞调用线程,直到队列中的所有任务被处理掉。

    只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。

    先进先出:

    import Queue
    q = Queue.Queue(maxsize=5)
    for i in range(5):
        q.put(i)
    while not q.empty():
        print q.get()

    结果:

    0
    1
    2
    3
    4
    View Code

    先进后出:

    q = Queue.LifoQueue()
    for i in range(5):
        q.put(i)
    while not q.empty():
        print q.get()

    结果:

    4
    3
    2
    1
    0
    View Code

    优先级:

    #优先级队列
    import Queue
    import threading
    class Job(object):
        def __init__(self, priority, description):
            self.priority = priority
            self.description = description
            print 'Job:',description
            return
        def __cmp__(self, other):           #需要加上这个比较函数,
            return cmp(self.priority, other.priority)   #Return negative if x<y, zero if x==y, positive if x>y.
    
    q = Queue.PriorityQueue()
    
    q.put(Job(3, 'mid-level job'))
    q.put(Job(10, 'low-level job'))
    q.put(Job(1, 'high-level job'))
    
    def process_job(q):
        while True:
            next_job = q.get()
            print 'for:', next_job.description
            q.task_done()
    
    workers = [threading.Thread(target=process_job, args=(q,)),
            threading.Thread(target=process_job, args=(q,))
            ]
    
    for w in workers:
        w.setDaemon(True)   #守护进程
        w.start()
    
    q.join()
    View Code

    运行结果:

    Job: mid-level job
    Job: low-level job
    Job: high-level job
    for: high-level job
    for: mid-level job
    for: low-level job
    View Code

    复杂一点的

    实现一个线程不断生成一个随机数到一个队列中(考虑使用Queue这个模块)
    实现一个线程从上面的队列里面不断的取出奇数
    实现另外一个线程从上面的队列里面不断取出偶数

    #!/usr/bin/python
    # coding=utf-8
    # __author__='dahu'
    # data=2017-
    #
    
    import random, threading, time
    from Queue import Queue
    
    
    # Producer thread
    class Producer(threading.Thread):
        def __init__(self, t_name, queue):
            # threading.Thread.__init__(self, name=t_name)
            super(Producer,self).__init__(name=t_name)  #两个都可以,倾向于这个
            self.data = queue
    
        def run(self):
            for i in range(5):  # 随机产生10个数字 ,可以修改为任意大小
                randomnum = random.randint(1, 20)
                print "%s: %s is producing %d to the queue!" % (time.ctime(), self.getName(), randomnum)
                self.data.put(randomnum)  # 将数据依次存入队列
                time.sleep(1)
            print "%s: %s finished!" % (time.ctime(), self.getName())
    
    
    # Consumer thread
    class Consumer_even(threading.Thread):
        def __init__(self, t_name, queue):
            # threading.Thread.__init__(self, name=t_name)
            super(Consumer_even, self).__init__(name=t_name)
            self.data = queue
    
        def run(self):
            while 1:
                try:
                    val_even = self.data.get(1, 5)  # get(self, block=True, timeout=None) ,1就是阻塞等待,5是超时5秒
                    if val_even % 2 == 0:
                        print "%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val_even)
                        time.sleep(2)
                    else:
                        self.data.put(val_even)
                        time.sleep(2)
                except:  # 等待输入,超过5秒  就报异常
                    print "%s: %s finished!" % (time.ctime(), self.getName())
                    break
    
    
    class Consumer_odd(threading.Thread):
        def __init__(self, t_name, queue):
            threading.Thread.__init__(self, name=t_name)
            self.data = queue
    
        def run(self):
            while 1:
                try:
                    val_odd = self.data.get(1, 5)
                    if val_odd % 2 != 0:
                        print "%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val_odd)
                        time.sleep(2)
                    else:
                        self.data.put(val_odd)
                        time.sleep(2)
                except:
                    print "%s: %s finished!" % (time.ctime(), self.getName())
                    break
    
    
    # Main thread
    def main():
        queue = Queue()
        producer = Producer('Pro.', queue)
        consumer_even = Consumer_even('Con_even.', queue)
        consumer_odd = Consumer_odd('Con_odd.', queue)
        producer.start()
        consumer_even.start()
        consumer_odd.start()
        producer.join()
        consumer_even.join()
        consumer_odd.join()
        print 'All threads terminate!'
    
    
    if __name__ == '__main__':
        main()
    View Code

    结果:

    /usr/bin/python2.7 /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t9.queue.thread.py
    Tue Aug 22 16:12:25 2017: Pro. is producing 15 to the queue!
    Tue Aug 22 16:12:25 2017: Con_odd. is consuming. 15 in the queue is consumed!
    Tue Aug 22 16:12:26 2017: Pro. is producing 17 to the queue!
    Tue Aug 22 16:12:27 2017: Pro. is producing 2 to the queue!
    Tue Aug 22 16:12:27 2017: Con_odd. is consuming. 17 in the queue is consumed!
    Tue Aug 22 16:12:28 2017: Pro. is producing 15 to the queue!
    Tue Aug 22 16:12:29 2017: Con_even. is consuming. 2 in the queue is consumed!
    Tue Aug 22 16:12:29 2017: Con_odd. is consuming. 15 in the queue is consumed!
    Tue Aug 22 16:12:29 2017: Pro. is producing 18 to the queue!
    Tue Aug 22 16:12:30 2017: Pro. finished!
    Tue Aug 22 16:12:31 2017: Con_even. is consuming. 18 in the queue is consumed!
    Tue Aug 22 16:12:38 2017: Con_odd. finished!
    Tue Aug 22 16:12:38 2017: Con_even. finished!
    All threads terminate!
    
    Process finished with exit code 0
  • 相关阅读:
    题解 CF171G 【Mysterious numbers
    题解 P1157 【组合的输出】
    题解 P3955 【图书管理员】
    题解 P2036 【Perket】
    题解 CF837A 【Text Volume】
    题解 CF791A 【Bear and Big Brother】
    题解 CF747A 【Display Size】
    题解 P1332 【血色先锋队】
    题解 P2660 【zzc 种田】
    题解 P4470 【[BJWC2018]售票】
  • 原文地址:https://www.cnblogs.com/dahu-daqing/p/7413420.html
Copyright © 2011-2022 走看看