python / python/cpython

`multiprocessing.Queue` methods have asymmetric behavior

Offen
#142,837 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

stdlib topic-multiprocessing type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

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

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginnen Sie mit der Dokumentation von multiprocessing.Queue zu qsize(), full() und empty(), und prüfen Sie anschließend die Reproduktion im Issue sowie die verwandten Issues #87302 und #128186. Sehen Sie sich den verknüpften PR #144832 an und bestimmen Sie, ob das Verhalten dort behoben ist; als erledigt gilt die Aufgabe, wenn entweder die Queue-Methoden konsistent funktionieren oder das dokumentierte Verhalten den gemeldeten Fall eindeutig abdeckt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
backend, distributed-systems
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.