14.3 The Queue Module
The Queue module
supplies first-in, first-out (FIFO) queues that support multithread
access, with one main class and two exception classes.
Queue is the main class for module
Queue and is covered in the next section. When
maxsize is greater than
0, the new Queue instance
q is deemed full when
q has maxsize
items. A thread inserting an item with the
block option, when
q is full, suspends until another thread
extracts an item. When maxsize is less
than or equal to 0, q
is never considered full, and is limited in size only by available
memory, like normal Python containers.
Empty is the class of the exception that
q.get(False) raises
when q is empty.
Full is the class of the exception that
q.put(x,False)
raises when q is full.
An instance q of class
Queue supplies the following methods.
Returns True if q is
empty, otherwise False.
Returns True if q is
full, otherwise False.
When block is False,
get removes and returns an item from
q if one is available, otherwise
get raises Empty. When
block is True,
get removes and returns an item from
q, suspending the calling thread, if need
be, until an item is available.
q.get_nowait( ) is like
q.get(False).
get removes and returns items in the same order as
put inserted them (first in, first out).
When block
is False, put adds
item to q if
q is not full, otherwise
put raises Full. When
block is True,
put adds item to
q, suspending the calling thread, if need
be, until q is not full.
q.put_nowait(item)
is like
q.put(item,False).
Returns the number of items that are currently in
q.
Queue offers a good example of the idiom
"it's easier to ask forgiveness
than permission" (EAFP), covered in Chapter 6. Due to multithreading, each non-mutating
method of q can only be advisory. When
some other thread executes and mutates q,
things can change between the instant a thread gets the information
and the very next moment, when the thread acts on the information.
Relying on the "look before you
leap" (LBYL) idiom is futile, and fiddling with
locks to try and fix things is a substantial waste of effort. Just
avoid LBYL code such as:
if q.empty( ): print "no work to perform"
else: x=q.get_nowait( )
and instead use the simpler and more robust EAFP approach:
try: x=q.get_nowait( )
except Queue.Empty: print "no work to perform"
|