2013-03-09 1 views
29

여러 파일에 대해 파이썬 코드를 병렬로 실행하려고합니다. 내가 이전에 비슷한 일을 할 pool.map을 사용했습니다 그것은 큰 일조인 할 때 파이썬 다중 처리 풀이 중단됩니까?

def process_file(filename, foo, bar, baz=biz): 
    # do stuff that may fail and cause exception 

if __name__ == '__main__': 
    # setup code setting parameters foo, bar, and biz 

    psize = multiprocessing.cpu_count()*2 
    pool = multiprocessing.Pool(processes=psize) 

    map(lambda x: pool.apply_async(process_file, (x, foo, bar), dict(baz=biz)), sys.argv[1:]) 
    pool.close() 
    pool.join() 

,하지만 난 pool.map가 (에 표시)하지 않기 때문에이 여기에 사용할 수없는 것 : 구축물은 기본적으로 (그리고 람다를 정렬 할 수 없기 때문에 람다를 사용하면 작동하지 않을 것입니다).

이제 apply_async()를 직접 사용하여 작업하게하려고합니다. 내 문제는 코드가 응답하지 않고 종료되지 않는 것입니다. 몇 가지 파일이 예외와 함께 실패하지만 왜 실패/중단에 대한 조인이 발생할 것이라고 볼 수 없습니까? 흥미롭게도 파일이 예외없이 실패하지 않으면 정상적으로 종료됩니다.

무엇이 누락 되었습니까?

편집 : 결코 아이를 수확하지 않고 종료 영원히

Exception in thread Thread-3: 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner 
    self.run() 
    File "/usr/lib/python2.7/threading.py", line 505, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "/usr/lib/python2.7/multiprocessing/pool.py", line 376, in _handle_results 
    task = get() 
TypeError: ('__init__() takes at least 3 arguments (1 given)', <class 'subprocess.CalledProcessError'>,()) 

난 이들 중 하나라도 나타나면 프로세스의 부모 프로세스가 응답 : 함수 (따라서 근로자가) 실패하면,이 예외를 참조 .

+0

'process_file'에 임의의 예외를 던지더라도 코드가 정상적으로 작동하는 것 같습니다. 그래서 아마 문제를 일으키는'process_file'에서 실제로하고있는 것과 관련이 있습니다. – robertklep

+0

허. 파이썬 버전은 무엇입니까? 나는 2.7에있어. 실제 프로그램의 process_file은 매우 복잡하여 PIL, NetworkX, poly2tri 및 기타 라이브러리를 많이 사용합니다. 어떤 경우에는 예외가 발생할 수있는 버그를 알고있는 곳이 적어도 2 곳은 알고 있지만, 단순히 오류를 무시하고 계속 진행해야합니다. 나는 그것이 결코 나를 위해 나가지 않을 것이지만 당신을 위해 일하는 것에 관해서 난처한 상태입니다. – clemej

+0

2.7.2 이것은 다음과 같이 테스트 한 내용입니다. https://gist.github.com/robertklep/5125319 – robertklep

답변

40

내 자신의 질문에 답변 해 드려 죄송합니다.하지만 다른 해결 방법이 있다면 비슷한 문제가 있으므로 여기에 게시하고 싶습니다. 나는 더 나은 대답을 받아 들일 것이다.

저는이 문제의 근원이 http://bugs.python.org/issue9400이라고 생각합니다. 난 미치지 않았어

  • , 그것은 피클 '예외'으로 불가능하지는 않지만 매우 어렵 내가 정말 적어도 python2에서
  • 작동하도록되어 할 노력하고있어 : 이것은 나에게 두 가지를 알려줍니다 부모 프로세스로 되돌아갑니다. 간단한 것들은 작동하지만 많은 다른 것들은 그렇지 않습니다.

내 경우에는 작업자 함수가 segfaulting 인 하위 프로세스를 시작하고있었습니다. 이 피 호출 할 수없는 CalledProcessError 예외가 반환되었습니다. 어떤 이유로 부모의 풀 객체가 점심 식사로 나가고 join() 호출에서 돌아 가지 않습니다.

내 경우에는 예외가 무엇인지 상관하지 않습니다. 기껏해야 나는 그것을 기록하고 계속 가고 싶다. 이렇게하려면 try/except 절에서 상위 작업자 함수를 간단하게 래핑합니다. 작업자가 예외를 throw하면 부모 프로세스로 돌아 가기 전에 캐치되고 기록되고 작업자 프로세스는 더 이상 예외를 보내려고하지 않으므로 정상적으로 종료됩니다. 아래를 참조하십시오 :

그런 다음 원래 맵 대신에 초기 맵 함수 호출 process_file_wrapped()가 있습니다. 이제 내 코드가 의도 한대로 작동합니다.

+7

질문에 대한 답변을 위해 사과하실 필요가 없습니다. 이 페이지는 이제 해결 방법과 함께 실제 문제를 문서화합니다. 좋습니다. –

+1

그건 그렇고, 또 다른 해결책은 단지 예외의 오류 메시지를 받아 기본 "예외"클래스를 사용하여 발생시키는 것일 수 있습니다.이 클래스는 피클 러블이라고 생각합니다. –

+1

저는 여전히 StackExchange를 처음 접했고 에티켓에 대해서는 확신이 없습니다. 위의 주석에서 @robertklep의 스 니펫이 일반 Exception()으로 작동한다면, 나도 괜찮을 것이라고 생각합니다.하지만 결론은 예외를 잡아서 알려진 작업을 반환해야한다는 것입니다. – clemej

4

lambda 대신 실제로 functools.partial 인스턴스를 사용할 수 있습니다. 피사체를 피클 링해야하는 경우입니다. partial 오브젝트는 Python 2.7부터 (그리고 Python 3에서) pickleable입니다.

pool.map(functools.partial(process_file, x, foo, bar, baz=biz), sys.argv[1:]) 
+0

흠. 나는 functools를 사용하지 않았다. 정보 주셔서 감사합니다. 나는 여전히 이것이 여전히 예외 예외 문제를 겪을 것이라고 생각한다. 아마도 – clemej

+0

아마도; 나는 말할 수 없다. 이전에'pool.map'을 성공했다고 언급 했으므로 아마도 도움이 될 것입니다. – nneonneo

+0

나는 상황이 예외를 일으키지 않는 완전히 다른 상황에서 pool.map을 사용했습니다. 나는 그 질문에 대해 분명히해야만했다. – clemej

2

pool.map이 걸렸을 때 나는 비슷한 버그가있었습니다. 유스 케이스를 사용하여 pool.terminate을 사용하여 문제를 해결할 수있었습니다 (물건을 바꾸기 전에 잘했는지 확인하십시오).

은 내가 docs에서 terminate 그래서 난 모든 것을 완성 알고 호출하기 전에 pool.map을 사용 :

지도의 병렬 등가() 내장 함수는 (그것이 비록 하나의 반복 가능한 인수를 지원합니다). 결과가 준비 될 때까지 차단됩니다.

이것이 유익한 경우 패치하는 방법 일 수 있습니다.

관련 문제