[Python-Dev] Making Queue.Queue easier to use
Josiah Carlson
jcarlson at uci.edu
Wed Oct 12 02:41:06 CEST 2005
[Guido]
> >> Apart from trying to guess the API without reading the docs (:-), what
> >> are the use cases for using put/get with a timeout? I have a feeling
> >> it's not that common.
[Josiah Carlson]
> > With timeout=0, a shared connection/resource pool (perhaps DB, etc., I
> > use one in the tuple space implementation I have for connections to the
> > tuple space).
[Tim Peters]
> Passing timeout=0 is goofy: use {get,put}_nowait() instead. There's
> no difference in semantics.
I understand this, as do many others who use it. However, having both
manually and automatically tuned timeouts myself in certain applications,
the timeout=0 case is useful. Uncommon? Likely, I've not yet seen any
examples of anyone using this particular timeout method at koders.com .
> > Note that technically speaking, Queue.Queue from Pythons
> > prior to 2.4 is broken: get_nowait() may not get an object even if the
> > Queue is full, this is caused by "elif not self.esema.acquire(0):" being
> > called for non-blocking requests. Tim did more than simplify the
> > structure by rewriting it, he fixed this bug.
>
> I don't agree it was a bug, but I did get fatally weary of arguing
> with people who insisted it was ;-) It's certainly easier to explain
> (and the code is easier to read) now.
When getting an object from a non-empty queue fails because some other
thread already had the lock, and it is a fair assumption that the other
thread will release the lock within the next context switch...
Because I still develop on Python 2.3 (I need to support a commercial
codebase made with 2.3), I was working around it by using the timeout
parameter:
try:
connection = connection_queue.get(timeout=.000001)
except Queue.Empty:
connection = make_new_connection()
With only get_nowait() calls, by the time I hit 3-4 threads, it was
failing to pick up connections even when there were hundreds in the
queue, and I quickly ran into the file handle limit for my platform, not
to mention that the server I was connecting to used asynchronous sockets
and select, which died at the 513th incoming socket.
I have since copied the implementation of 2.4's queue into certain
portions of code which make use of get_nowait() and its variants
(handline the deque reference as necessary).
Any time one needs to work around a "not buggy feature" with some
claimed "unnecessary feature", it tends to smell less than pristine to
my nose.
> > With block=True, timeout=None, worker threads pulling from a work-to-do
> > queue, and even a thread which handles the output of those threads via
> > a result queue.
>
> Guido understands use cases for blocking and non-blocking put/get, and
> Queue always supported those possibilities. The timeout argument got
> added later, and it's not really clear _why_ it was added. timeout=0
> isn't a sane use case (because the same effect can be gotten with
> non-blocking put/get).
def t():
try:
#thread state setup...
while not QUIT:
try:
work = q.get(timeout=5)
except Queue.Empty:
continue
#handle work
finally:
#thread state cleanup...
Could the above be daemonized? Certainly, but then the thread state
wouldn't be cleaned up. If you can provide me with a way of doing the
above with equivalent behavior, using only get_nowait() and get(), then
put it in the documentation. If not, then I'd say that the timeout
argument is a necessarily useful feature.
[Guido]
> But one lesson we can learn from sockets (or perhaps the reason why
> people kept asking for timeout=0 to be "fixed" :) is that timeout=0 is
> just a different way to spell blocking=False. The socket module makes
> sure that the socket ends up in exactly the same state no matter which
> API is used; and in fact the setblocking() API is redundant.
This would suggest to me that at least for sockets, setblocking() could
be deprecated, as could the block parameter in Queue. I wouldn't vote
for either deprecation, but it would seem to make more sense than to
remove the timeout arguments from both.
- Josiah
More information about the Python-Dev
mailing list