Queue enhancement suggestion
Jean-Paul Calderone
exarkun at divmod.com
Mon Apr 16 19:35:55 EDT 2007
On 15 Apr 2007 23:12:34 -0700, Paul Rubin <"http://phr.cx"@nospam.invalid> wrote:
>I'd like to suggest adding a new operation
>
> Queue.finish()
>
>This puts a special sentinel object on the queue. The sentinel
>travels through the queue like any other object, however, when
>q.get() encounters the sentinel, it raises StopIteration instead
>of returning the sentinel. It does not remove the sentinel from
>the queue, so further calls to q.get also raise StopIteration.
>That permits writing the typical "worker thread" as
>
> for item in iter(q.get): ...
>
>without having to mess with the task-counting stuff that recently got
>added to the Queue module. The writing end of the queue simply
>calls .finish() when it's done adding items.
>
>Someone in an earlier thread suggested
>
> # writing side
> sentinel = object()
> q.put(sentinel)
>
> ...
> # reading side
> for item in iter(q.get, sentinel): ...
>
>however that actually pops the sentinel, so if there are a lot of
>readers then the writing side has to push a separate sentinel for
>each reader. I found my code cluttered with
>
> for i in xrange(number_of_worker_threads):
> q.put(sentinel)
>
>which certainly seems like a code smell to me.
Instead of putting multiple sentinels, just pre-construct the iterator
object.
work = iter(q.get, sentinel)
Re-use the same iterator in each thread, and you'll get the behavior
you're after.
Jean-Paul
More information about the Python-list
mailing list