4

나는 꽤 오랫동안 사용되지 않았지만 이미 사용되어 잘 작동 한 프로그램이 있습니다. 여러 데이터에 대해 동일한 작업을 여러 번 수행해야하므로 다중 처리가 사용됩니다.프로그램은 map()과 함께 작동하지만 pool.map()을 사용하여 TypeError를 발생시킵니다.

이제 새 매개 변수를 추가하는 프로그램을 만져서 테스트 한 결과 오류가 있음을 알았습니다. 또한 이전 (버전 제어) 버전도 동일한 오류가 발생합니다. 전체 오류는 다음과 같습니다.

Exception in thread Thread-2: 
    Traceback (most recent call last): 
     File "/usr/lib64/python2.7/threading.py", line 811, in __bootstrap_inner 
      self.run() 
     File "/usr/lib64/python2.7/threading.py", line 764, in run 
      self.__target(*self.__args, **self.__kwargs) 
     File "/usr/lib64/python2.7/multiprocessing/pool.py", line 342, in _handle_tasks 
      put(task) 
TypeError: 'NoneType' object is not callable 

그게 전부입니다. 그것은 솔직히 말해서 나에게별로 말하지 않습니다. 이것을 디버깅하는 동안 풀 버전 pool.map 대신 일반 map()을 사용하려고했습니다. 스크립트가 정상적으로 실행됩니다.

내가 오류를 재현 최소한의 예를, 가지고 올 수는 없지만, 내가 기대했던대로 모든 것이 잘 작동 예를 들어, 가지고 올 수 :

import random 
import time 
from multiprocessing import Pool 


def do_work(x, y, z): 
    time.sleep(random.random() * 2) 
    print x + y + z 

def do_one(arguments): 
    print "doing one" 
    do_work(*arguments) 

def do_many(x, y, zs): 
    map(do_one, [(x, y, z) for z in zs]) 

def do_many_pooled(x, y, zs): 
    pool = Pool(2) 
    pool.map(do_one, [(x, y, z) for z in zs]) 
    pool.close() 
    pool.join() 

def main(): 
    x = 1 
    y = 2 
    zs = range(10) 
    print "doing many" 
    do_many(x, y, zs) 
    print "doing many pooled" 
    do_many_pooled(x, y, zs) 


if __name__ == '__main__': 
    main() 

실제 프로그램을 많이하지 데이터베이스 요청, numpy를 사용한 계산 및 결과를 다시 데이터베이스에 저장. 실제 프로그램에서 풀링 된 버전과 함께 사용할 때는 "one one"을 인쇄하기 전에 오류없이 프로그램이 종료되지만 풀링되지 않은 버전을 사용하면 문제없이 실행됩니다.

누군가가 어떻게 트레이스 백을 올바르게 읽는 지, 그리고/또는이 예외를 유발할 수있는 원인을 알 수 있습니까?

+0

[map_async] (https://docs.python.org/2/library/multiprocessing.html#multiprocessing.pool.multiprocessing.Pool.map_async)를 사용하고 [AsyncResult] (https : // docs .python.org/2/library/multiprocessing.html # multiprocessing.pool.AsyncResult) 예외를 재발견하기위한'get' 메소드와 더 많은 정보를 찾을 수 있을까요? – NoamG

+0

어떤 버전의 파이썬을 사용하고 있습니까? 파이썬 2.7. 뭐라구? – jszakmeister

+0

@tobias_k 예, 100 % 확신합니다. 본문에서 언급했듯이이 예제에서는 오류를 재현 할 수 없으며 최소한의 예제로 오류를 재현하는 데 필요한 것이 무엇인지 알지 못합니다. – Nras

답변

2

나는 put이 역 추적이 부분에서 없음에 대한 설정을 사방되고있는 것 같습니다 말할 것 : Pool.__init__()는 할 것이다 _task_handler 을 설정하는 것입니다, 파이썬 소스를 보면

File "/usr/lib64/python2.7/multiprocessing/pool.py", line 342, in _handle_tasks 
    put(task) 
TypeError: 'NoneType' object is not callable 

당신이,884,321 보면

self._task_handler = threading.Thread(
    target=Pool._handle_tasks, 
    args=(self._taskqueue, self._quick_put, self._outqueue, self._pool) 
    ) 

: _handle_tasks에 전화 의 인수를 제공하고 전화를했다 0, 당신은 self._quick_putput 변수 인 을 종료 무엇을 볼 :

@staticmethod 
def _handle_tasks(taskqueue, put, outqueue, pool, cache): 
    thread = threading.current_thread() 

    for taskseq, set_length in iter(taskqueue.get, None): 
     i = -1 
     for i, task in enumerate(taskseq): 
      if thread._state: 
       debug('task handler found thread._state != RUN') 
       break 
      try: 
       put(task) 
      except Exception as e: 
       job, ind = task[:2] 
       try: 
        cache[job]._set(ind, (False, e)) 
       except KeyError: 
        pass 
     else: 
      if set_length: 
       debug('doing set_length()') 
       set_length(i+1) 
      continue 
     break 
    else: 
     debug('task handler got sentinel') 

또한, 모든 예외가 여기 잡은 이후보고 을 자리 잡고되고있는 것을 볼 수 있습니다. 다시 파이썬 2.7.6에 머리를하지만,이 나타납니다하십시오 TypeError 탈출 할 수 있다고 여기

@staticmethod 
def _handle_tasks(taskqueue, put, outqueue, pool): 
    thread = threading.current_thread() 

    for taskseq, set_length in iter(taskqueue.get, None): 
     i = -1 
     for i, task in enumerate(taskseq): 
      if thread._state: 
       debug('task handler found thread._state != RUN') 
       break 
      try: 
       put(task) 
      except IOError: 
       debug('could not put task on queue') 
       break 
     else: 
      if set_length: 
       debug('doing set_length()') 
       set_length(i+1) 
      continue 
     break 
    else: 
     debug('task handler got sentinel') 

알 수 있습니다. 버그 #19425의 결과로 이것은 으로 수정되었습니다. 이상하게도, 이것은 으로 파이썬 2.7에서는 문제가되지 않았지만 변경 세트는 여전히 으로 역 분개되었다.

어쨌든 put()은 알려진 값이어야하며 은이 코드에서 put을 설정하는 방법으로는 표시되지 않습니다. 그래서, 저에게는 파이썬에서 버그 과 같은 냄새가납니다. 새로운 버전의 Python에서 동일한 코드를 실행할 수 있습니까?

일부 기타 유용한 정보 빠른 구글 검색도 몇 가지 흥미로운 결과를 반환

:

  • 파이썬 버그 #9755 - 유사하지만 서로 다른 스택 추적.

  • 파이썬 버그 #15881 - 위와 마찬가지로 과 약간 다른 스택 추적도 있습니다.

모두 정리가 " 'NoneType'객체가 호출되지 않습니다"예외와 함께 실패 모듈 상태에 영향을 미치는와 에 일을 일으키는 문제입니다.

기타, 다소 관련 버그가 Python에도 존재했습니다. 한 번에 데몬 스레드를 사용하고 응용 프로그램의 기본 스레드 인 을 종료하는 것과 비슷한 예외가 발생할 수 있습니다. 고정 된 버전을 잊어 버렸습니다. 그냥 이런 종류의 문제가 전례가 아니며 버그가 있음을 보여주고 싶었습니다. Python.

+0

힌트를 보내 주셔서 감사 드리며, 내일 시도하고 결과를 업데이트 해 드리겠습니다. 편집 : 이것에 대해 생각해 보면, 왜 코드가 이전에 성공적으로 실행 되었습니까? 제가 아는 한, 파이썬 2.7.x였습니다. 집에서 x를 모르지만, x가 바뀌지 않았을 것이라는 확신이 듭니다. – Nras

+0

말하기 어렵습니다. 물건이 어떻게 움직이고, 찢어 지는지에 따라, 뭔가 불쾌한 일이 일어나고있는 상황에 처해있을 수 있습니다 (예 : 무언가가 당신 아래에서 쓰레기로 수집되고 있음). stacktrace는 확실히 이상한데, 그것이 왜 그런 수수께끼인가하는 것입니다. :-( – jszakmeister

+0

필자가 디버깅을한다면, 호출하기 전에 put 값을 출력하는 것으로 시작하겠다. 예, 설치된 Python 코드를 수정하는 것이지만, 시작해야 할 부분이다. – jszakmeister