当需要按照先进先出的顺序存储和处理数据时,可以使用 Python 中的队列(Queue)模块。在这个模块中,可以找到几个队列类型,其中最常用的是先进先出队列(FIFO)。
创建一个队列
在 Python 中创建一个队列很简单。只需要使用队列模块中的 Queue
类来创建就可以了。下面是一个简单的示例:
import queue
# 创建一个空的先进先出队列
q = queue.Queue()
创建了一个空的先进先出队列之后,就可以向这个队列中添加数据,或者从队列中提取数据了。
向队列中添加数据
向队列中添加数据有两个方法,分别是 put
和 put_nowait
。其中,put
方法是将数据放入队列中,并且在必要时阻塞,直到队列有空间可用。而 put_nowait
方法则是将数据放入队列中,如果队列已满,则会引发 queue.Full
异常。下面是一个向队列中添加数据的示例:
import queue
# 创建一个空的先进先出队列
q = queue.Queue()
# 使用 put 方法向队列中添加数据(方法会阻塞)
q.put(1)
q.put(2)
q.put(3)
# 使用 put_nowait 方法向队列中添加数据(方法不会阻塞)
q.put_nowait(4)
q.put_nowait(5)
q.put_nowait(6)
从队列中提取数据
从队列中提取数据也有两个方法,分别是 get
和 get_nowait
。其中,get
方法是将数据从队列中取出,并且在必要时阻塞,直到队列中有数据。而 get_nowait
方法则是将数据从队列中取出,如果队列为空,则会引发 queue.Empty
异常。下面是一个从队列中提取数据的示例:
import queue
# 创建一个先进先出队列
q = queue.Queue()
# 向队列中添加数据
q.put(1)
q.put(2)
q.put(3)
# 从队列中取出数据
print(q.get()) # 输出:1
print(q.get()) # 输出:2
print(q.get()) # 输出:3
# 使用 get_nowait 方法从队列中取出数据(方法不会阻塞)
try:
print(q.get_nowait()) # 输出:queue.Empty 异常
except queue.Empty:
print("队列为空")
示例说明:
接下来,我们用一个更加具体的实例说明如何使用队列。
假设我们要使用队列来实现一个生产者-消费者模式。生产者会不断地生成数据,并将数据放入到一个队列中,而消费者会不断地从队列中取出数据,并对数据进行处理。下面是使用两个线程来实现的生产者-消费者模式的示例:
import queue
import threading
# 创建一个队列
q = queue.Queue()
# 数据生成者函数
def producer():
for i in range(5):
# 生成数据
data = "Data{}".format(i)
# 将生成的数据放入队列中
q.put(data)
print("[生产者{}]: 生成了数据 {}".format(threading.current_thread().name, data))
# 数据消费者函数
def consumer():
while True:
try:
# 从队列中取出数据
data = q.get(timeout=5)
except queue.Empty:
print("[消费者{}]: 队列为空,退出线程".format(threading.current_thread().name))
break
# 对数据进行处理
print("[消费者{}]: 处理数据 {}".format(threading.current_thread().name, data))
# 创建两个线程,一个线程作为生产者,一个线程作为消费者
t1 = threading.Thread(target=producer, name="生产者1")
t2 = threading.Thread(target=consumer, name="消费者1")
# 启动线程
t1.start()
t2.start()
# 等待线程结束
t1.join()
t2.join()
在这个示例中,我们首先创建了一个队列,然后创建了两个线程。线程 t1
作为生产者,会不断地生成数据,并将数据放入队列中;线程 t2
作为消费者,会不断地从队列中取出数据,并对数据进行处理。这个示例中的队列就是用来作为生产者和消费者之间的数据传输介质的。在实现中,如果队列为空,消费者就会等待一段时间,然后再次尝试从队列中获取数据。如果连续多次获取不到数据,那么消费者线程就会结束。