python / python/cpython

`multiprocessing.Queue` methods have asymmetric behavior

Aperta
#142,837 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

stdlib topic-multiprocessing type-bug
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug report

Bug description:

Currently, the qsize() and full() methods rely on the semaphore value (they change their result immediately after the put operation is performed). However, the empty() method relies on the underlying pipe's readiness, which violates user expectations (since similar queue.Queue methods have symmetric behavior) and leads to the following:

#!/usr/bin/env python3

import sys
import time

from multiprocessing import Process, Queue, set_start_method

CONSUMERS = 100  # any sufficiently large number
ITEMS = CONSUMERS * 100  # should result in exceeding the underlying pipe
DELAY = 1  # "infinitesimal", but it can actually be as large as you like


def consume(queue):
    for _ in range(ITEMS // CONSUMERS):
        if queue.empty():  # it should never be printed, but it will be
            print("EMPTY!")

        queue.get()


def main():
    queue = Queue()

    for i in range(ITEMS):
        queue.put(i)

    time.sleep(DELAY)
    assert queue.qsize() == ITEMS

    consumers = [
        Process(target=consume, args=[queue], daemon=True)
        for _ in range(CONSUMERS)
    ]

    for consumer in consumers:
        consumer.start()

    for consumer in consumers:
        consumer.join()


if __name__ == "__main__":
    set_start_method("fork")
    sys.exit(main())

The problem was initially noticed in one Stack Overflow question, when the queue was considered empty despite having a sufficiently large number of items. I have only cited one case, but in fact the problem will always occur when buffer flushing is too slow (especially if any complex objects are serialized).

I decided to mark this as a bug, as this behavior can be fixed as a result of solving #87302. Otherwise, I think clarifying this point in the documentation may also be sufficient.

Related (implicitly used in the above code to reproduce): #128186.

CPython versions tested on:

3.9, 3.10, 3.11, 3.12, 3.13, 3.14

Operating systems tested on:

Linux

Linked PRs
  • gh-144832

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con la documentazione di multiprocessing.Queue relativa a qsize(), full() ed empty(), quindi esamina la riproduzione nell’issue e le issue correlate #87302 e #128186. Controlla la PR collegata #144832 e determina se il comportamento è stato risolto lì; il lavoro è considerato completato se i metodi della queue si comportano in modo coerente oppure se il comportamento documentato affronta chiaramente il caso segnalato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
backend, distributed-systems
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.