对于Python队列(Queue)的深入阐述

简介: 对于Python队列(Queue)的深入阐述

对于Python队列(Queue)的深入阐述

一 . 什么是队列 , 队列的作用是什么??

在Python中,队列(Queue)是一种数据结构,用于在元素的一端进行插入操作,而在另一端进行删除操作,遵循先进先出(FIFO)的原则。在Python中,你可以使用内置模块 queue 提供的 Queue 类来实现队列数据结构

在生活中,队列是一种常见的现象,可以用来描述等待服务的场景。考虑以下生活中的例子:排队购物。

假设你去了一家超市,现在有几个顾客需要结账。超市通常会设置一个收银台队列,顾客按照先来先服务的原则排队等待结账。这里的排队过程就类似于一个队列,新来的顾客排在队列的尾部,而第一个来的顾客首先被服务。

from queue import Queue
import threading
import time
def cashier(queue):
    while True:
        customer = queue.get()
        print(f"顾客 {customer} 结账完成")
        time.sleep(1)  # 模拟结账过程
# 创建一个队列
checkout_queue = Queue()
# 创建一个收银员线程
cashier_thread = threading.Thread(target=cashier, args=(checkout_queue,), daemon=True)
cashier_thread.start()
# 模拟顾客排队结账
for customer_number in range(1, 6):
    checkout_queue.put(customer_number)
    time.sleep(0.5)  # 模拟顾客进队列的间隔
cashier_thread.join()  # 等待收银员线程结束

让我们深入解析上述 Python 代码,它模拟了一个简化的生活中排队购物的场景。

from queue import Queue
import threading
import time

导入了 Queue 类,以及用于多线程的模块 threadingtime 模块,用于模拟时间的流逝。

def cashier(queue):
    while True:
        customer = queue.get()
        print(f"顾客 {customer} 结账完成")
        time.sleep(1)  # 模拟结账过程

定义了一个函数 cashier,它模拟了收银员的行为。这个函数一直运行,不断从队列中取出顾客的编号,然后模拟结账过程,最后输出结账完成的消息。

# 创建一个队列
checkout_queue = Queue()

创建了一个 Queue 对象,用于模拟购物结账的排队队列。

# 创建一个收银员线程
cashier_thread = threading.Thread(target=cashier, args=(checkout_queue,), daemon=True)
cashier_thread.start()

创建了一个线程对象 cashier_thread,并指定了 target 参数为 cashier 函数,即该线程的执行内容是 cashier 函数。args 参数传递了 checkout_queue,作为 cashier 函数的参数。daemon=True 表示这是一个守护线程,当主线程结束时,它会随之结束。

# 模拟顾客排队结账
for customer_number in range(1, 6):
    checkout_queue.put(customer_number)
    time.sleep(0.5)  # 模拟顾客进队列的间隔

模拟了五个顾客依次排队进入结账队列,每次排队的间隔是 0.5 秒。

cashier_thread.join()  # 等待收银员线程结束

使用 join() 方法等待 cashier_thread 线程结束,确保在主线程结束前,所有的子线程都已经执行完毕。

总体来说,这个例子通过队列和多线程模拟了一个简单的生活场景,其中多个顾客排队等待收银员进行结账,而收银员通过队列按照先来先服务的原则依次为顾客服务。

二 . 队列的使用语法

在Python中,queue 模块提供了 Queue 类,用于实现队列。以下是基本的队列使用语法:

  1. 创建队列:
from queue import Queue
# 创建一个队列
my_queue = Queue()
  1. 向队列中添加元素:
my_queue.put(1)
my_queue.put(2)
my_queue.put(3)
  1. 使用 put 方法将元素添加到队列的尾部。
  2. 从队列中取出元素:
element1 = my_queue.get()
element2 = my_queue.get()
  1. 使用 get 方法从队列的头部取出元素。如果队列为空,get 方法将会阻塞,直到队列中有元素可取。
  2. 判断队列是否为空:
is_empty = my_queue.empty()
  1. 使用 empty 方法判断队列是否为空。返回 True 表示队列为空,False 表示队列不为空。
  2. 获取队列的大小:
size = my_queue.qsize()
  1. 使用 qsize 方法获取队列中元素的个数。

以上是 Queue 类的一些基本用法。除了 Queuequeue 模块还提供了其他一些队列的实现,例如 LifoQueue(后进先出队列)和 PriorityQueue(带有优先级的队列)。这些队列类的基本使用方法是相似的,但有些差异,可以根据实际需求选择适合的队列类型。

三 . 队列的使用

  • multiprocessing.Queue 提供了一个简单的队列,允许多个进程通过放置和获取消息来进行通信。队列是线程安全的,可以用于在多进程之间安全地传递数据。
pythonCopy code
from multiprocessing import Process, Queue
def worker(queue):
    data = queue.get()
    # 进行处理
    print(data)
if __name__ == "__main__":
    my_queue = Queue()
    process = Process(target=worker, args=(my_queue,))
    process.start()
    my_queue.put("Hello from the main process")
    process.join()

四 . queue.get/queue.put的使用

在Python中,queue.get() 是用于从队列中获取数据的方法。这通常用于在多线程或多进程的环境中进行线程间或进程间的安全数据传递。

multiprocessing 模块或 queue 模块中,get() 方法是一个阻塞调用,意味着如果队列中没有可用的数据,调用 get() 的线程或进程将会等待,直到有数据可供获取。一旦有数据可用,get() 会返回队列中的下一个元素,并将其从队列中移除。

以下是一个使用 queue.get() 的简单示例,其中有一个生产者线程往队列中放置数据,一个消费者线程从队列中获取数据:

pythonCopy code
import threading
import queue
import time
def producer(q):
    for i in range(5):
        time.sleep(1)
        item = f"Item-{i}"
        q.put(item)
        print(f"Produced: {item}")
def consumer(q):
    while True:
        item = q.get()
        if item is None:
            break
        print(f"Consumed: {item}")
if __name__ == "__main__":
    my_queue = queue.Queue()
    # 启动生产者线程
    producer_thread = threading.Thread(target=producer, args=(my_queue,))
    producer_thread.start()
    # 启动消费者线程
    consumer_thread = threading.Thread(target=consumer, args=(my_queue,))
    consumer_thread.start()
    # 等待生产者线程完成
    producer_thread.join()
    # 停止消费者线程
    my_queue.put(None)
    consumer_thread.join()

在这个例子中,producer 线程生产数据并将其放入队列,而 consumer 线程从队列中获取并处理这些数据。为了结束 consumer 线程,可以通过在队列中放入 None(或其他特殊标记)来表示队列结束。

这段代码是一个简单的多线程示例,演示了一个生产者线程往队列中放入数据,以及一个消费者线程从队列中获取数据的情况。为了停止消费者线程,特意在队列中放入了一个 None 来表示队列的结束。

具体分析如下:

  1. 导入模块:
pythonCopy code
import threading
import queue
import time
  1. 导入了用于多线程编程的 threading 模块,队列模块 queue,以及用于控制时间的 time 模块。
  2. 定义生产者函数 producer:
pythonCopy code
def producer(q):
    for i in range(5):
        time.sleep(1)
        item = f"Item-{i}"
        q.put(item)
        print(f"Produced: {item}")
  1. producer 函数模拟了生产者的行为,往队列中放入了5个数据,每个数据间隔1秒。
  2. 定义消费者函数 consumer:
pythonCopy code
def consumer(q):
    while True:
        item = q.get()
        if item is None:
            break
        print(f"Consumed: {item}")
  1. consumer 函数是一个循环,不断从队列中获取数据,如果获取到的数据是 None,则跳出循环,表示消费结束。
  2. 主程序:
pythonCopy code
if __name__ == "__main__":
    my_queue = queue.Queue()
    # 启动生产者线程
    producer_thread = threading.Thread(target=producer, args=(my_queue,))
    producer_thread.start()
    # 启动消费者线程
    consumer_thread = threading.Thread(target=consumer, args=(my_queue,))
    consumer_thread.start()
    # 等待生产者线程完成
    producer_thread.join()
    # 停止消费者线程
    my_queue.put(None)
    consumer_thread.join()
  • 创建了一个线程安全的队列 my_queue
  • 启动了一个生产者线程和一个消费者线程。
  • 等待生产者线程完成(producer_thread.join()),确保生产者线程执行完毕。
  • 往队列中放入 None,表示队列结束。
  • 等待消费者线程完成(consumer_thread.join()),确保消费者线程执行完毕。

这个例子展示了一个简单的生产者-消费者模型,其中生产者和消费者在不同的线程中运行,并通过队列进行数据传递。

相关文章
|
4月前
|
数据采集 存储 安全
如何确保Python Queue的线程和进程安全性:使用锁的技巧
本文探讨了在Python爬虫技术中使用锁来保障Queue(队列)的线程和进程安全性。通过分析`queue.Queue`及`multiprocessing.Queue`的基本线程与进程安全特性,文章指出在特定场景下使用锁的重要性。文中还提供了一个综合示例,该示例利用亿牛云爬虫代理服务、多线程技术和锁机制,实现了高效且安全的网页数据采集流程。示例涵盖了代理IP、User-Agent和Cookie的设置,以及如何使用BeautifulSoup解析HTML内容并将其保存为文档。通过这种方式,不仅提高了数据采集效率,还有效避免了并发环境下的数据竞争问题。
如何确保Python Queue的线程和进程安全性:使用锁的技巧
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 09. 用两个栈实现队列
使用两个栈实现队列的Python解决方案,包括初始化两个栈、实现在队列尾部添加整数的appendTail方法和在队列头部删除整数的deleteHead方法,以及相应的示例操作。
41 2
|
4月前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
5月前
|
数据采集 Python
Python多进程:如何在不依赖Queue的情况下传递结果
本文探讨了在Python中使用多进程技术采集抖音短视频数据时,如何在不依赖队列(Queue)的情况下传递结果。文章首先介绍了多进程提高数据采集效率的背景,然后指出了队列在处理大量数据时可能成为性能瓶颈,并增加了系统复杂性。作为解决方案,提出了使用管道、共享内存和临时文件等替代方法。文章通过一个实战案例,详细演示了如何配置爬虫代理、设置请求头、实现定时器装饰器、抓取视频数据以及通过管道在子进程间传递结果。最后,文章总结了使用这些替代方案可以有效提高数据采集的效率和可靠性。
Python多进程:如何在不依赖Queue的情况下传递结果
|
4月前
|
Python
【python】】Python 的 queue 模块使用笔记
【python】】Python 的 queue 模块使用笔记
48 0
|
4月前
|
前端开发 Python
数据结构Python用队列实现杨辉三角形
数据结构Python用队列实现杨辉三角形
37 0
|
4月前
|
Python
[Python]队列基础
[Python]队列基础
|
4月前
|
Python
【Leetcode刷题Python】641.循环双端队列
文章介绍了如何实现一个循环双端队列,包括其操作如插入、删除、获取队首和队尾元素,以及检查队列是否为空或已满,并提供了Python语言的实现代码。
25 0
|
4月前
|
Python
【Leetcode刷题Python】232. 用栈实现队列
如何使用Python语言通过两个栈来实现队列的所有基本操作,包括入队(push)、出队(pop)、查看队首元素(peek)和判断队列是否为空(empty),并提供了相应的代码实现。
22 0
|
4月前
|
Python
Python IPC深度探索:解锁跨进程通信的无限可能,以管道与队列为翼,让你的应用跨越边界,无缝协作,震撼登场
【8月更文挑战第3天】Python IPC大揭秘:解锁进程间通信新姿势,让你的应用无界连接
28 0