# Files d'attente (queues)

Code source : Lib/asyncore.py

Les files d'attente asyncio sont conçues pour être similaires aux classes du module `queue`. Bien que les files d'attente asyncio ne soient pas compatibles avec les programmes à multiples fils d'exécution, elles sont conçues pour être utilisées spécifiquement dans le code async/await.

Notez que les méthodes des files d'attente asyncio n'ont pas de paramètre timeout ; utilisez la fonction `asyncio.wait_for()` pour effectuer des opérations de file d'attente avec un délai d'attente.

Voir également la section Exemples ci-dessous.

## File d'attente (queue)

class asyncio.Queue(maxsize=0)

  File d'attente premier entré, premier sorti (FIFO pour fist in, first out).

  Si maxsize est inférieur ou égal à zéro, la taille de la file d'attente est infinie. Si c'est un entier supérieur à `0`, alors `await put()` se bloque lorsque la file d'attente atteint maxsize jusqu'à ce qu'un élément soit supprimé par `get()`.

  Contrairement à la bibliothèque standard multi-fils `queue`, la taille de la file d'attente est toujours connue et peut être renvoyée en appelant la méthode `qsize()`.

  Modifié dans la version 3.10: suppression du paramètre loop.

  Cette classe n'est pas compatible avec les fils d'exécution multiples.

  maxsize

    Nombre d'éléments autorisés dans la file d'attente.

  empty()

    Renvoie `True` si la file d'attente est vide, `False` sinon.

  full()

    Renvoie `True` s'il y a `maxsize` éléments dans la file d'attente.

    If the queue was initialized with `maxsize=0` (the default), then `full()` never returns `True`.

  async get()

    Supprime et renvoie un élément de la file d'attente. Si la file d'attente est vide, attend qu'un élément soit disponible.

    Raises `QueueShutDown` if the queue has been shut down and is empty, or if the queue has been shut down immediately.

  get_nowait()

    Renvoie un élément s'il y en a un immédiatement disponible, sinon lève `QueueEmpty`.

  async join()

    Bloque jusqu'à ce que tous les éléments de la file d'attente aient été récupérés et traités.

    Le nombre de tâches inachevées augmente chaque fois qu'un élément est ajouté à la file. Ce nombre diminue chaque fois qu'un fil d'exécution consommateur appelle `task_done()` pour indiquer que l'élément a été extrait et que tout le travail à effectuer dessus est terminé. Lorsque le nombre de tâches non terminées devient nul, `join()` débloque.

  async put(item)

    Met un élément dans la file d'attente. Si la file d'attente est pleine, attend qu'un emplacement libre soit disponible avant d'ajouter l'élément.

    Raises `QueueShutDown` if the queue has been shut down.

  put_nowait(item)

    Ajoute un élément dans la file d'attente sans bloquer.

    Si aucun emplacement libre n'est immédiatement disponible, lève `QueueFull`.

  qsize()

    Renvoie le nombre d'éléments dans la file d'attente.

  shutdown(immediate=False)

    Put a `Queue` instance into a shutdown mode.

    The queue can no longer grow. Future calls to `put()` raise `QueueShutDown`. Currently blocked callers of `put()` will be unblocked and will raise `QueueShutDown` in the formerly awaiting task.

    If immediate is false (the default), the queue can be wound down normally with `get()` calls to extract tasks that have already been loaded.

    And if `task_done()` is called for each remaining task, a pending `join()` will be unblocked normally.

    Once the queue is empty, future calls to `get()` will raise `QueueShutDown`.

    If immediate is true, the queue is terminated immediately. The queue is drained to be completely empty and the count of unfinished tasks is reduced by the number of tasks drained. If unfinished tasks is zero, callers of `join()` are unblocked. Also, blocked callers of `get()` are unblocked and will raise `QueueShutDown` because the queue is empty.

    Use caution when using `join()` with immediate set to true. This unblocks the join even when no work has been done on the tasks, violating the usual invariant for joining a queue.

    Ajouté dans la version 3.13.

  task_done()

    Indicate that a formerly enqueued work item is complete.

    Used by queue consumers. For each `get()` used to fetch a work item, a subsequent call to `task_done()` tells the queue that the processing on the work item is complete.

    Si un `join()` est actuellement bloquant, on reprendra lorsque tous les éléments auront été traités (ce qui signifie qu'un appel à `task_done()` a été effectué pour chaque élément qui a été `put()` dans la file).

    Lève une exception `ValueError` si elle est appelée plus de fois qu'il n'y avait d'éléments dans la file.

## File avec priorité

class asyncio.PriorityQueue

  Une variante de `Queue` ; récupère les entrées par ordre de priorité (la plus basse en premier).

  Les entrées sont généralement des n-uplets de la forme `(priority_number, data)`.

## Pile (LIFO)

class asyncio.LifoQueue

  Une variante de `Queue` qui récupère en premier les entrées les plus récemment ajoutées (dernier entré, premier sorti).

## Exceptions

exception asyncio.QueueEmpty

  Cette exception est levée lorsque la méthode `get_nowait()` est appelée sur une file d'attente vide.

exception asyncio.QueueFull

  Exception levée lorsque la méthode `put_nowait()` est appelée sur une file d'attente qui a atteint sa maxsize.

exception asyncio.QueueShutDown

  Exception raised when `put()` or `get()` is called on a queue which has been shut down.

  Ajouté dans la version 3.13.

## Exemples

Les files d'attente peuvent être utilisées pour répartir la charge de travail entre plusieurs tâches simultanées :

    import asyncio
    import random
    import time

    async def worker(name, queue):
        while True:
            # Get a "work item" out of the queue.
            sleep_for = await queue.get()

            # Sleep for the "sleep_for" seconds.
            await asyncio.sleep(sleep_for)

            # Notify the queue that the "work item" has been processed.
            queue.task_done()

            print(f'{name} has slept for {sleep_for:.2f} seconds')

    async def main():
        # Create a queue that we will use to store our "workload".
        queue = asyncio.Queue()

        # Generate random timings and put them into the queue.
        total_sleep_time = 0
        for _ in range(20):
            sleep_for = random.uniform(0.05, 1.0)
            total_sleep_time += sleep_for
            queue.put_nowait(sleep_for)

        # Create three worker tasks to process the queue concurrently.
        tasks = []
        for i in range(3):
            task = asyncio.create_task(worker(f'worker-{i}', queue))
            tasks.append(task)

        # Wait until the queue is fully processed.
        started_at = time.monotonic()
        await queue.join()
        total_slept_for = time.monotonic() - started_at

        # Cancel our worker tasks.
        for task in tasks:
            task.cancel()
        # Wait until all worker tasks are cancelled.
        await asyncio.gather(*tasks, return_exceptions=True)

        print('====')
        print(f'3 workers slept in parallel for {total_slept_for:.2f} seconds')
        print(f'total expected sleep time: {total_sleep_time:.2f} seconds')

    asyncio.run(main())