2011-08-18 2 views
3

파이썬의 패키지 다중 처리 및 큐를 사용하는 프로그램이 있습니다. 내 기능 중 하나는이 구조를 가지고 :파이썬 다중 처리에서 빈 큐 확인

from multiprocessing import Process, Queue 
def foo(queue): 
    while True: 
     try: 
      a = queue.get(block = False) 
      doAndPrintStuff(a) 
     except: 
      print "the end" 
      break 

    if __name__ == "__main__" 
    nthreads = 4 
    queue = Queue.Queue() 
    # put stuff in the queue here 
    for stuff in moreStuff: 
     queue.put(stuff) 
    procs = [Process(target = foo, args = (queue,)) for i in xrange(nthreads)] 
    for p in procs: 
     p.start() 
    for p in procs: 
     p.join() 

생각 나는 큐에서 추출하려고이 비어있을 때, 그것은 예외를 발생하고, 루프를 종료 할 것이라는 점이다. 그래서 두 가지 질문이 있습니다 :

1) 이것은 안전한 관용구입니까? 이 작업을 수행하는 더 좋은 방법이 있습니까?

2) 빈 큐에서 .get()을 시도 할 때 발생하는 정확한 예외가 무엇인지 찾으려고 노력했습니다. 현재 나의 프로그램은 모든 예외를 잡아 내고 있으며, 오류가 다른 곳에서 발생하면 "나는 끝"메시지 만 받는다.

내가 시도 :

import Queue 
    queue = Queue.Queue() 
    [queue.put(x) for x in xrange(10)] 
    try: 
     print queue.get(block = False) 
    except Queue.Empty: 
     print "end" 
     break 

하지만 난 예외를 잡은 않은 것처럼 나는 오류가 발생했습니다. 잡을 올바른 예외는 무엇입니까?

답변

10

예외는 Queue.Empty이어야합니다. 하지만 과 같은 오류가 발생 했습니까? 두 번째 예에서 대기열 자체를 multiprocessing.Queue에서 Queue.Queue으로 전환했는데 문제 일 수 있습니다.

그것은 이상하게 보일 수도 있지만, 당신은 multiprocessing.Queue 클래스를 사용하지만,

+0

험! 감사! 나는 다른 패키지에서 물건을 가져와야한다는 것을 몰랐다. 이제 작동합니다. –

0

queue 라이브러리 문서를 읽어보십시오. Queue.empty()을 찾고 계시지 않습니까?

2

큐가 풋 버퍼 때까지 비어있는 것으로 보인다 (당신이 Queue 모듈에서 자신을 가져올 필요가 있음) Queue.Empty 예외를 사용해야합니다 플러시 된, 어느 정도 걸릴 수 있습니다.

우리의 문제에 대한 해결책은 to usesentinels, 아니면입니다 내장 task_done() 전화 :

task_done()

가 이전 큐에 작업이 완료되었음을 나타냅니다. 큐 소비자 스레드가 사용합니다. 작업을 가져 오는 데 사용되는 각 get()에 대해 후속 task_done()을 호출하면 작업 처리가 으로 완료되었음을 대기열에 알립니다.

현재 join()이 차단 중이면 모든 항목이 처리되었을 때 다시 시작됩니다. 즉, 대기열에 put() 된 모든 항목에 대해 에 대한 task_done() 호출이 수신되었습니다.

대기열에있는 항목보다 호출 횟수가 많으면 ValueError를 발생시킵니다.