la gestion de file par python: Queue

Python possède le module Queue qui permet de gérer une file d’attente.

ce module est très pratique car il intègre sur la file:

  • le mode de gestion (LIFO, FIFO, Priorité)
  • la taille de la file
  • l’ajout et la suppresion d’éléments dans cette file

les principales types de queues

  • Queue.Queue(maxsize=0)
  • Queue.LifoQueue(maxsize=0)
  • Queue.PriorityQueue(maxsize=0)

on peut pour chaque type de queue indiquer le nombre maximal d’élément

les principales fonctions

  • Queue.qsize()
  • Queue.empty()
  • Queue.full()
  • Queue.put(item[, block[, timeout]])
  • Queue.put_nowait(item)
  • Queue.get([block[, timeout]])
  • Queue.get_nowait()
  • Queue.task_done()
  • Queue.join()

Il faut noter que par défaut la fonction

  • get qu’un élément existe dans la file pour le donner
  • put attend qu’une place dans la file se libère une place pour mettre l’élément

exemple simple d’utilisation simple

import Queue

q = Queue.Queue()

for i in range(5):
    q.put(i)

while not q.empty():
    print q.get()

le module queue est souvent utilisé avec les Thread.

On peut ainsi réaliser des tâches en parallèle avec une synchronisation finale

Par exemple on va réaliser 3 tâches, chaque tâche fournit un nombre utilisé par une tâche finale pour réaliser une somme

programme réalisant ce travail de façon classique

import time, random
import datetime

print datetime.datetime.now()

sum = 0
for i in range(0,3):
    a = random.randint(1, 10)
    time.sleep(a)
    sum = sum + a

print "somme:  ", sum
print datetime.datetime.now()

le résultat

2013-05-25 11:30:31.931000
somme:   16
2013-05-25 11:30:47.931000

En utilisant les thread et les queues pour la synchronisation

import time, random
import datetime

import threading, Queue

class Calcul(threading.Thread):
    def __init__(self, q):
        threading.Thread.__init__(self)
        self.q = q

    def run(self):
        a = random.randint(1, 10)
        time.sleep(a)
        self.q.put(a)

print datetime.datetime.now()
sum= 0
queue = Queue.Queue(3)

for i in range(0,3):
    Calcul(queue).start()

while queue.qsize() != 3:
    time.sleep(0.1) #on attend 100ms

for i in range(0,3):
    sum = sum + queue.get()

print "somme:  ", sum
print datetime.datetime.now()

le résultat

2013-05-25 11:41:42.756000
somme:   12
2013-05-25 11:41:47.788000

avec la méthode simple il nous aurait fallu 12s il la seulement 5s