¿Cómo poner los artículos en colas de prioridad?

En los documentos de Python,

Las entradas con el valor más bajo se recuperan primero (la entrada con el valor más bajo es la que se devuelve sorted(list(entries))[0] ). Un patrón típico para las entradas es una tupla en la forma: (priority_number, data) .

Parece que la cola se ordenará por prioridad y luego por datos, lo que puede no ser siempre correcto. Supongamos que los datos del “elemento 2” se ponen en cola antes del “elemento 1”, el elemento 1 seguirá siendo el primero. En otra página de documentos, heapq , sugiere el uso de un contador. Así que almacenaré mis datos como entry = [priority, count, task] . No hay algo como

 PriorityQueue.put(item, priority) 

¿Entonces no necesitaré implementar el pedido yo mismo?

Por lo que sé, lo que estás buscando no está disponible de forma inmediata. De todos modos, tenga en cuenta que no sería difícil de implementar:

 from Queue import PriorityQueue class MyPriorityQueue(PriorityQueue): def __init__(self): PriorityQueue.__init__(self) self.counter = 0 def put(self, item, priority): PriorityQueue.put(self, (priority, self.counter, item)) self.counter += 1 def get(self, *args, **kwargs): _, _, item = PriorityQueue.get(self, *args, **kwargs) return item queue = MyPriorityQueue() queue.put('item2', 1) queue.put('item1', 1) print queue.get() print queue.get() 

Ejemplo de salida:

 item2 item1 

Solo use el segundo elemento de la tupla como una prioridad secundaria si una ordenación alfanumérica en sus datos de cadena no es apropiada. Una prioridad de fecha / hora le daría una cola de prioridad que regresa a una cola FIFIO cuando tiene varios elementos con la misma prioridad. Aquí hay un código de ejemplo con solo una prioridad numérica secundaria. Usar un valor de fecha y hora en la segunda posición es un cambio bastante trivial, pero no dude en introducirme en los comentarios si no puede hacerlo funcionar.

Código

 import Queue as queue prio_queue = queue.PriorityQueue() prio_queue.put((2, 8, 'super blah')) prio_queue.put((1, 4, 'Some thing')) prio_queue.put((1, 3, 'This thing would come after Some Thing if we sorted by this text entry')) prio_queue.put((5, 1, 'blah')) while not prio_queue.empty(): item = prio_queue.get() print('%s.%s - %s' % item) 

Salida

 1.3 - This thing would come after Some Thing if we didn't add a secondary priority 1.4 - Some thing 2.8 - super blah 5.1 - blah 

Editar

Esto es lo que parece si usa una marca de tiempo para falsificar FIFO como una prioridad secundaria usando una fecha. Digo falso porque solo es aproximadamente FIFO, ya que las entradas que se agregan muy cerca entre sí pueden no ser exactamente FIFO. Agregué un breve descanso para que este simple ejemplo funcione de una manera razonable. Esperemos que esto sirva de ayuda como otro ejemplo de cómo puede obtener el pedido que está buscando.

 import Queue as queue import time prio_queue = queue.PriorityQueue() prio_queue.put((2, time.time(), 'super blah')) time.sleep(0.1) prio_queue.put((1, time.time(), 'This thing would come after Some Thing if we sorted by this text entry')) time.sleep(0.1) prio_queue.put((1, time.time(), 'Some thing')) time.sleep(0.1) prio_queue.put((5, time.time(), 'blah')) while not prio_queue.empty(): item = prio_queue.get() print('%s.%s - %s' % item) 

Hice algo como esto para lograr un FIFO similar a gfortune, pero sin la necesidad de llamar a time.time () en todas partes: (solo Python 3)

 import time from dataclasses import dataclass, field @dataclass(order=True) class PrioritizedItem: prio: int timestamp: float = field(init=False, default_factory=time.time) data: object = field(compare=False) 

Ahora puedes hacer:

 import queue item1 = PrioritizedItem(0, "hello world") item2 = PrioritizedItem(0, "what ever") q = queue.PriorityQueue() q.put(item1) q.put(item2) 

Y seguro, siempre se extraerán en el mismo orden.