Как выполнить итерацию через Queue.Queue Python с циклом for вместо цикла while?
Обычно мы кодируем его так:
while not queue.empty():
try:
job = queue.get()
Но возможно ли что-то сделать в строках:
for job in queue.get():
#do stuff to job
Настоящая причина, по которой я хочу это сделать, - это то, что я хотел использовать maxval. Они делают это как for this in progressbar(that):
Ответы
Ответ 1
Вы можете использовать iter
с возможностью вызова. (Вы должны передать два аргумента, один для вызываемого, другой для значения дозорного)
for job in iter(queue.get, None): # Replace `None` as you need.
# do stuff with job
ПРИМЕЧАНИЕ Это будет заблокировано, если элемент не останется и не будет отправлено значение дозорного значения.
Ответ 2
Для такой очереди я обычно не использовал бы эту проверку queue.empty()
, потому что я всегда использую ее в поточном контексте и, следовательно, не могу знать, будет ли другой поток помещать что-то там за несколько миллисекунд (таким образом, чтобы проверка быть бесполезным в любом случае). Я никогда не проверяю очередь на то, чтобы быть пустым. Я скорее использую значение сторожевого знака, которое знаменует окончание продюсера.
Таким образом, использование iter(queue.get, Sentinel)
больше того, что мне нравится.
Если вы знаете, что ни один другой поток больше не будет помещать элементы в очередь и просто хочет вытереть его из всех содержащихся в данный момент элементов, вы можете использовать sth следующим образом:
class Drainer(object):
def __init__(self, q):
self.q = q
def __iter__(self):
while True:
try:
yield self.q.get_nowait()
except queue.Empty: # on python 2 use Queue.Empty
break
for item in Drainer(q):
print(item)
или
def drain(q):
while True:
try:
yield q.get_nowait()
except queue.Empty: # on python 2 use Queue.Empty
break
for item in drain(q):
print(item)
Ответ 3
Мое первое, хотя было для функции iter, но встроенный модуль очереди не возвращает дозорный сигнал, поэтому хорошей альтернативой может быть определение вашего собственного класса-оболочки:
import Queue
class IterableQueue():
def __init__(self,source_queue):
self.source_queue = source_queue
def __iter__(self):
while True:
try:
yield self.source_queue.get_nowait()
except Queue.Empty:
return
Этот итератор обертывает очередь и возвращает до тех пор, пока очередь не будет пустой, а затем вернется, так что теперь вы можете сделать:
q = Queue.Queue()
q.put(1)
q.put(2)
q.put(3)
for n in IterableQueue(q):
print(n)
Вывод:
1
2
3
Этот метод немного подробный, было бы интересно, если кто-нибудь знает что-нибудь лучше, используя встроенные функции.
Ответ 4
list(q.queue)
q = Queue.Queue()
for elem in list(q.queue):
print elem
Я предпочитаю это над iter(queue.get
, поскольку он не полагается на часового.
Выучено из: Как перебирать элементы Queue.Queue в Python?
Ответ 5
Для стандартного итеративного объекта Python вы можете просто использовать:
for job in queue:
#do stuff to job