用 Python 的 heapq 模块,十行代码实现一个高优先级任务队列.
写代码的时候,总会遇到需要排队的情况。普通队列先进先出,但真实场景里总有意外。比如下载文件时突然来了个紧急更新,或者处理用户请求时VIP用户需要插队。这种时候就要用优先级队列。今天分享一个用Python自带heapq模块实现的高优先级任务队列,代码不到十行。
先讲个真实经历。之前写爬虫程序,要抓取几千个网页。普通队列按顺序爬,结果重要页面老是排到后面。领导催着要数据,我只能手动调顺序,搞得手忙脚乱。后来用了优先级队列,给重要任务设高优先级,它们会自动插到前面。这个小改动让工作效率提升不少。
实现原理简单说就是利用堆数据结构。堆是一种特殊的二叉树,能保证每次取出的都是最小(或最大)元素。Python的heapq模块帮我们封装好了堆操作,直接用就行。
核心代码就这几行:
import heapq
class PriorityQueue:
def __init__(self):
self.queue = []
self.counter = 0
def push(self, task, priority=0):
heapq.heappush(self.queue, (priority, self.counter, task))
self.counter += 1
def pop(self):
if self.queue:
return heapq.heappop(self.queue)[-1]
return None
这段代码做了什么?push方法把任务和优先级打包成元组放进堆里,pop方法取出优先级最高的任务。这里有个小细节:加了个计数器,确保相同优先级的任务按添加顺序执行。
使用方法很简单。创建队列对象后,queue.push('普通任务')、queue.push('紧急任务', priority=-10)。优先级数值越小越靠前,所以用负数表示高优先级。调用queue.pop()就能拿到当前最该处理的任务。
实际项目中我把这个队列用在任务调度系统里。数据库里有几十万条待处理记录,每条记录都有紧急程度字段。用这个队列处理后,系统先处理紧急程度高的记录。以前需要写很复杂的条件判断,现在一行代码搞定。
需要注意的是,heapq模块不是线程安全的。多线程环境下要加锁,或者用queue.PriorityQueue这个线程安全版本。不过单线程场景下直接用heapq更轻量,性能也好。
还有一个实用技巧。如果任务本身包含多个属性,可以用namedtuple封装。比如:
from collections import namedtuple
Task = namedtuple('Task', ['name', 'data'])
这样队列里存的就不是简单字符串,而是结构化数据。推入时写queue.push(Task('下载', url='xxx'), priority=-5)就行。
优先级队列的价值在于让代码逻辑更简洁。不用手动维护任务顺序,不用写复杂的排序逻辑,交给堆结构自动化处理。十行代码解决了实际开发中的痛点,这就是Python生态的魅力。你可以在每日任务列表、消息处理系统、爬虫调度中试试这个方案。