2011-12-13 8 views
24

저는 파이썬 객체 지향에 익숙하지 않고 개발자가 증가하고 있으며 코드가 유지 보수가 불가능 해지고 있기 때문에 객체 지향 버전으로 기존 응용 프로그램을 다시 작성하고 있습니다.파이썬 서브 클래 싱 다중 처리. 프로세스

는 일반적으로 나는 다중 큐를 사용하지만 나는 그래서 나는 그것이 좋은 생각 multiprocessing.Process을 하위 클래스 예 http://www.doughellmann.com/PyMOTW/multiprocessing/basics.html에서 발견하고이 같은 테스트 할 수있는 클래스 썼다 :

코드 :

from multiprocessing import Process 
class Processor(Process): 
    def return_name(self): 
     return "Process %s" % self.name 
    def run(self): 
     return self.return_name() 

processes = [] 


if __name__ == "__main__": 

     for i in range(0,5): 
       p=Processor() 
       processes.append(p) 
       p.start() 
     for p in processes: 
       p.join() 

그러나 값을 다시 가져올 수 없습니다.이 방법으로 큐를 어떻게 사용할 수 있습니까?

편집 : 반환 값을 얻고 싶고 Queues()을 넣을 곳을 원합니다.

답변

28

서브 클래스 multiprocessing.Process :이 방법으로

내가 값을 다시 얻을 수 없다 그러나, 어떻게 사용할 수있는 큐?

프로세스 ... 내 컴퓨터에

from multiprocessing import Process, Queue 
class Processor(Process): 

    def __init__(self, queue, idx, **kwargs): 
     super(Processor, self).__init__() 
     self.queue = queue 
     self.idx = idx 
     self.kwargs = kwargs 

    def run(self): 
     """Build some CPU-intensive tasks to run via multiprocessing here.""" 
     hash(self.kwargs) # Shameless usage of CPU for no gain... 

     ## Return some information back through multiprocessing.Queue 
     ## NOTE: self.name is an attribute of multiprocessing.Process 
     self.queue.put("Process idx={0} is called '{1}'".format(self.idx, self.name)) 

if __name__ == "__main__": 
    NUMBER_OF_PROCESSES = 5 

    ## Create a list to hold running Processor object instances... 
    processes = list() 

    q = Queue() # Build a single queue to send to all process objects... 
    for i in range(0, NUMBER_OF_PROCESSES): 
     p=Processor(queue=q, idx=i) 
     p.start() 
     processes.append(p) 

    # Incorporating ideas from this answer, below... 
    # https://stackoverflow.com/a/42137966/667301 
    [proc.join() for proc in processes] 
    while not q.empty(): 
     print "RESULT: {0}".format(q.get()) # get results from the queue... 

는,이 결과 ... multiprocessing.Process은 다음 서브 클래 싱하는 방법의 예를 결과를받을 Queue()을 필요로

$ python test.py 
RESULT: Process idx=0 is called 'Processor-1' 
RESULT: Process idx=4 is called 'Processor-5' 
RESULT: Process idx=3 is called 'Processor-4' 
RESULT: Process idx=1 is called 'Processor-2' 
RESULT: Process idx=2 is called 'Processor-3' 
$ 


multiprocessing.Pool :

FWIW, multiprocessing.Process의 서브 클래 싱을 발견 한 단점은 multiprocessing.Pool의 기본 제공되는 모든 장점을 활용할 수 없다는 것입니다. Pool은 매우 좋은 API를 제공합니다. 생산자 및 소비자 코드가 대기열을 통해 서로 통신해야합니다.

다음과 같은 예에서, 내가 pool_job()에서 입력 및 출력 값을 캡슐화하는 dict()를 사용 ... 그냥 창조적 반환 값을 많이 할 수 있습니다 ...

from multiprocessing import Pool 

def pool_job(input_val=0): 
    # FYI, multiprocessing.Pool can't guarantee that it keeps inputs ordered correctly 
    # dict format is {input: output}... 
    return {'pool_job(input_val={0})'.format(input_val): int(input_val)*12} 

pool = Pool(5) # Use 5 multiprocessing processes to handle jobs... 
results = pool.map(pool_job, xrange(0, 12)) # map xrange(0, 12) into pool_job() 
print results 

이 결과 :

[ 
    {'pool_job(input_val=0)': 0}, 
    {'pool_job(input_val=1)': 12}, 
    {'pool_job(input_val=2)': 24}, 
    {'pool_job(input_val=3)': 36}, 
    {'pool_job(input_val=4)': 48}, 
    {'pool_job(input_val=5)': 60}, 
    {'pool_job(input_val=6)': 72}, 
    {'pool_job(input_val=7)': 84}, 
    {'pool_job(input_val=8)': 96}, 
    {'pool_job(input_val=9)': 108}, 
    {'pool_job(input_val=10)': 120}, 
    {'pool_job(input_val=11)': 132} 
] 

분명히 오류 처리와 같이 pool_job()에는 많은 개선 사항이 있지만 분명히 필수적입니다. FYI this answermultiprocessing.Pool을 사용하는 방법에 대한 또 다른 예를 제공합니다.

+0

을 그래서,에 메서드 중 하나가 매개 변수 오른쪽으로 Queue 객체를 받아 들여야합니까? –

+0

완료! 큐를 수락하는 init 메서드를 만들었습니다. 이 차례로 멀티 프로세싱을 확장합니다. 직접 큐를 수락하는 프로세스 : –

+0

정정 주셔서 감사. 이 코드'return self.queue.put (self.return_name())'은 큐를 반환합니까? –

2

Process.run의 반환 값은 어디에도 없습니다. 상위 프로세스로 다시 보내야합니다 (예 : multiprocessing.Queue (docs here)을 사용하십시오.

2

많은 분들께 감사드립니다.

지금 heres는 내가 그것을 내가 각 ohter 사이에 있지만 부모 프로세스와 통신하지 않는 여러 queus을 사용하여이 예에서

: 수행 됐는지.

from multiprocessing import Process,Queue 
class Processor(Process): 
    def __init__(self,queue): 
     Process.__init__(self) 
     self.que=queue 
    def get_name(self): 
     return "Process %s" % self.name 
    def run(self): 
     self.que.put(self.get_name()) 



if __name__ == "__main__": 

     processes = [] 
     for i in range(0,5): 
       p=Processor(Queue()) 
       processes.append(p) 
       p.start() 
     for p in processes: 
       p.join() 
       print p.que.get() 
+0

으로 전달하고 있습니다. 내 코드를 검토하고 좀 더 파이썬적이고 더 나은 방법으로 개선 할 수있는 것을 알려주십시오. –

+0

당신은'super()'를 사용해야합니다 ... 내 게시물을보십시오 ... –

+0

감사합니다. 그러나 나는 supers가 위험한 특히 다중 상속을 읽었다? 그게 사실이야? –

2

Mike's answer은 최고입니다, 그러나 다만 완성도 나는 그렇게 마지막 비트는 다음과 같이 보일 것이다 join 상황에서 큐를 수확 을 선호 언급 할 :

[proc.join() for proc in processes] # 1. join 

while not q.empty(): # 2. get the results 
    print "RESULT: %s" % q.get()