2012-07-21 6 views
7

En el doc de qsize() dice: Devuelve el tamaño aproximado de la cola.¿Por qué Python's Queue devuelve un tamaño aproximado en qsize()?

¿Por qué no puede simplemente devolver el tamaño exacto de esta cola? Entiendo que se puede acceder a la cola por varios hilos, pero en el momento en que llamo a la función creo que todavía es posible devolver el tamaño exacto de ese momento.

+1

¿Qué momento? El tamaño de la cola puede haber cambiado durante el retorno del método. –

Respuesta

24

Es precisamente porque hay otros subprocesos que acceden a él. Para cuando intente utilizar el tamaño que obtiene de qsize(), la cola podría haber cambiado. Sería mejor si la documentación dijera algo como esto:

Devuelve el tamaño de la cola. Tenga en cuenta que en un entorno de subprocesos múltiples, el tamaño puede cambiar en cualquier momento, por lo que esto es solo una aproximación del tamaño real.

5

Estoy de acuerdo que 'aproximado' no es la más clara elección de palabras, pero como menciona Ned que están tratando de señalar que, simplemente porque el tamaño de la cola en el momento t1 era 7 no quiere decir que se siga siendo el tamaño 7 cuando presione o muestre valores más adelante.

El problema es que, suponiendo que el tamaño que obtenga de qsize siga siendo correcto cuando pase a push/pop, un valor fuera de esa cola puede comportarse inesperadamente en un entorno de subprocesos múltiples.

Por ejemplo:

q = Queue() 
if q.qsize > 0: # size is 1 here 
    # another thread runs here and gets an item from your queue 
    # this get fails and throws an exception in your thread: 
    item = q.get(False) 
    # do whatever processing with item you need to do 

Este es un ejemplo de LBYL "Buscando antes de saltar" y es peligroso debido a la condición de carrera potencial aquí cuando varios subprocesos tienen acceso a la cola.

En este caso, debería favorecer EAFP o "más fácil pedir perdón que pedir permiso" y hacer lo siguiente:

from Queue import Queue, Empty 
import time 
q = Queue() 
try: 
    item = q.get(False) 
    # do whatever processing with item you need to do 
except Empty: 
    time.sleep(1) 
+0

.. o simplemente use un semáforo para garantizar que la cola tenga una entrada. –

+6

La cola ya está sincronizada, no agregue más en la parte superior. Usar 'q.get' con una excepción es la mejor forma de seguridad de subprocesos para obtener un artículo. –

Cuestiones relacionadas