[Python-ideas] `__iter__` for queues?

George Sakkis george.sakkis at gmail.com
Wed Jan 20 21:56:38 CET 2010


On Wed, Jan 20, 2010 at 9:36 PM, Raymond Hettinger
<raymond.hettinger at gmail.com> wrote:
>
> On Jan 20, 2010, at 3:59 AM, cool-RR wrote:
>
> On Wed, Jan 20, 2010 at 7:24 AM, Anh Hai Trinh <anh.hai.trinh at gmail.com>
> wrote:
>>
>> [...]
>>
>> I agree, however, that this should be left out of the stdlib API.
>>
>> --
>> // aht
>
> Okay, but what about having an object like `Queue.dump` (or some other name
> instead of `dump`), which can be iterated? This will be similar to
> `dict.keys` and `dict.values`.
>
> I think you need to abandon the notion of iteration
> and instead focus on your original use case of
> (destructively) pulling all of the items out of a queue.
> Taking a cue (no pun intended) from the DB-API's
> fetchone() and fetchall(), perhaps you're looking for
> a getall() method?
>
>     def get_all(self, block=True, timeout=None):
>         """Remove and return all items from the queue.
>         If optional args 'block' is true and 'timeout' is None (the
> default),
>         block if necessary until an item is available. If 'timeout' is
>         a positive number, it blocks at most 'timeout' seconds and raises
>         the Empty exception if no item was available within that time.
>         Otherwise ('block' is false), return an item if one is immediately
>         available, else raise the Empty exception ('timeout' is ignored
>         in that case).
>         """
>         self.not_empty.acquire()
>         try:
>             if not block:
>                 if not self._qsize():
>                     raise Empty
>             elif timeout is None:
>                 while not self._qsize():
>                     self.not_empty.wait()
>             elif timeout < 0:
>                 raise ValueError("'timeout' must be a positive number")
>             else:
>                 endtime = _time() + timeout
>                 while not self._qsize():
>                     remaining = endtime - _time()
>                     if remaining <= 0.0:
>                         raise Empty
>                     self.not_empty.wait(remaining)
>             result = []
>             while self._qsize():
>                 result.append(self._get())
>             self.not_full.notify()
>             return result
>         finally:
>             self.not_empty.release()

It's not obvious to me what "all" should mean, or even if it makes
sense, in the default case (`block=True, timeout=None`) when there are
no items. IIUC, the implementation above makes it effectively
equivalent to get() in this case, i.e. a list with a single-item is
returned. Although that's reasonable, it seems arbitrary. I'd find
more intuitive a method with signature `get_all(self, timeout=0.0)`,
which by default is equivalent to the `block=False` above, and
equivalent to `block=True, timeout=timeout` if timeout>0.

George



More information about the Python-ideas mailing list