2017-09-14 7 views
0

Windows에서 Eclipse를 실행할 때 다음 코드를 얻는 데 문제가 있습니다. 코드는 Doug Hellman에서입니다 :python 다중 처리 pickling/manager/misc 오류 (PMOTW에서)

import random 
import multiprocessing 
import time 


class ActivePool: 

    def __init__(self): 
     super(ActivePool, self).__init__() 
     self.mgr = multiprocessing.Manager() 
     self.active = self.mgr.list() 
     self.lock = multiprocessing.Lock() 

    def makeActive(self, name): 
     with self.lock: 
      self.active.append(name) 

    def makeInactive(self, name): 
     with self.lock: 
      self.active.remove(name) 

    def __str__(self): 
     with self.lock: 
      return str(self.active) 


def worker(s, pool): 
    name = multiprocessing.current_process().name 
    with s: 
     pool.makeActive(name) 
     print('Activating {} now running {}'.format(
      name, pool)) 
     time.sleep(random.random()) 
     pool.makeInactive(name) 


if __name__ == '__main__': 
    pool = ActivePool() 
    s = multiprocessing.Semaphore(3) 
    jobs = [ 
     multiprocessing.Process(
      target=worker, 
      name=str(i), 
      args=(s, pool), 
     ) 
     for i in range(10) 
    ] 

    for j in jobs: 
     j.start() 

    for j in jobs: 
     j.join() 
     print('Now running: %s' % str(pool)) 

내가 Process에 인수로 pool 전달로 인해 일부 산세 문제에 내가 가정 다음과 같은 오류를 얻을.

Traceback (most recent call last): 
    File "E:\Eclipse_Workspace\CodeExamples\FromCodes\CodeTest.py", line 50, in <module> 
    j.start() 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\process.py", line 105, in start 
    self._popen = self._Popen(self) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\context.py", line 223, in _Popen 
    return _default_context.get_context().Process._Popen(process_obj) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\context.py", line 322, in _Popen 
    return Popen(process_obj) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__ 
    reduction.dump(process_obj, to_child) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\reduction.py", line 60, in dump 
    ForkingPickler(file, protocol).dump(obj) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\connection.py", line 939, in reduce_pipe_connection 
    dh = reduction.DupHandle(conn.fileno(), access) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\connection.py", line 170, in fileno 
    self._check_closed() 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\connection.py", line 136, in _check_closed 
    raise OSError("handle is closed") 
OSError: handle is closed 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\spawn.py", line 99, in spawn_main 
    new_handle = reduction.steal_handle(parent_pid, pipe_handle) 
    File "C:\Users\Bob\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\reduction.py", line 87, in steal_handle 
    _winapi.DUPLICATE_SAME_ACCESS | _winapi.DUPLICATE_CLOSE_SOURCE) 
PermissionError: [WinError 5] Access is denied 

비슷한 질문의 answer 내가 최고 수준의 함수 호출로 pool를 초기화하는 것이 좋습니다 것 같다,하지만 난이 예에 그것을 적용하는 방법을 모르겠어요. 에 ActivePool을 초기화합니까? 그것은 헬만의 모범을 무너 뜨리는 것 같습니다.

또 다른 answer 내가 unpickleable 개체를 제거하고 unpickling 때를 재구성하는 __getstate__, __setstate__를 사용 제안,하지만 난 프록시 관리자 같은 개체 함께 할 수있는 좋은 방법을 알고하지 않으며, 실제로 무엇을 모르는 unpickleable 객체입니다.

최소한의 변경만으로이 예제를 작동시킬 수있는 방법이 있습니까? 두포에서 무슨 일이 벌어지고 있는지 이해하고 싶습니다. 감사!

편집 - 문제 해결 :

산 세척 문제가 돌이켜 보면 꽤 분명했습니다. ActivePool의 __init__에 unpicklable 인 Manager() 개체가 포함되어 있습니다. 우리가 self.mgr을 제거하고 한 줄의 목록 ProxyObject를 초기화하면 코드는 헬먼의 예에 따라 정상적으로 실행 : 읽기

def __init__(self): 
     super(ActivePool, self).__init__() 
     self.active = multiprocessing.Manager().list() 
     self.lock = multiprocessing.Lock() 

답변

0

Comment: The 'join()' was in the Hellman example, but I forgot to add it into the code snippet. Any other ideas?

내가 리눅스를 사용하고있어 예상대로, 윈도우는 다른 행동 작품 understanding-multiprocessing-shared-memory-management-locks-and-queues-in-pyt

args=(s, pool)의 어떤 매개 변수가 오류를 일으키는 지 확인하려면 global으로 사용하십시오.
변경 :

def worker(s): 
    ... 

     args=(s,), 

Note: There is no need to enclose a multiprocessing.Manager().list() with a Lock() .
This is not the culprit of your error.


Question: Is there any way I can make this example work with minimal changes?

귀하의 __main__ 프로세스가 종료 따라서 모든 프로세스가 실행 예상치 못한 위치에 죽을 시작했다.

for j in jobs: 
     j.join() 

    print('EXIT __main__') 

파이썬으로 테스트 : 모든 프로세스가 완료 될 때까지 __main__ 대기를 수 있도록 끝 부분에 간단 .join() 추가 나는 모든 잠금 호출을 주석 3.4.2

+0

과 같은 오류가 . Hellman 예제에서 'join()'이 사용되었지만이를 코드 스 니펫에 추가하는 것을 잊었습니다. 다른 아이디어? – Zhulu

+0

이 문제를 해결하기 전에 글로벌 세마포 및 글로벌 풀 핸들을 작성한 다음 args (s,), args (pool,), args (s, pool)로 코드를 실행했습니다. 3 명 모두 불행하게도 작동하지 않았습니다.두 번째와 세 번째 방법은 동일한 오류를 발생 시켰으며 첫 번째 방법은'AttributeError : NoneType '객체에'makeActive '속성이 없었습니다. 나는 전역을 만들었고 그것들을'pool = None'과 'def initialize_pool() : global pool \ pool = ActivePool()'처럼 초기화했습니다. – Zhulu