2016-07-13 2 views
1

파일이나 전역 변수를 읽는 데 파이썬 다중 처리를 테스트했지만 뭔가 이상합니다. expample에 대한이상한 일이 파이썬 다중 프로세스에서 발생합니다.

는 :

import multiprocessing 

a = 0 

def test(lock, name):  
    global a 
    with lock:   
     for i in range(10): 
      a = a + 1 
     print "in process %d : %d" % (name, a) 

def main():  
    lock = multiprocessing.Lock()    

    p1 = multiprocessing.Process(target=test, args=(lock, 1)) 
    p2 = multiprocessing.Process(target=test, args=(lock, 2)) 

    p1.start() 
    p2.start() 

    p1.join() 
    p2.join() 

    print "in main process : %d" % a 

if __name__=='__main__': 
    main() 

이 프로그램은 전역 변수를 읽을 수 있지만 출력은 다음과 같습니다

in process 1 : 10 
in process 2 : 10 
in main process : 0 

그것은 하위 프로세스가 얻을 제대로 전역 변수를 편집 할 수 없습니다 것으로 보인다. 또한 파일을 읽도록 프로그램을 변경하면 각 하위 프로세스는 잠금을 무시하고 파일을 완전히 읽습니다.

그렇다면 어떻게 될까요? 그리고이 문제를 해결하는 방법?

+0

난 당신이 당신은 멀티 스레딩 대신 동시 실행을 위해 멀티 프로세싱 사용할 수있는'multiprocessing.Manager' – mgilson

+0

를 사용하여 글로벌 상태를 관리해야합니다 믿습니다 예를 들면 다음과 같습니다이다. 모든 스레드는 단일 프로세스의 일부입니다. – VPfB

답변

1

전역 변수는 프로세스간에 공유되지 않습니다. 새 Process()을 만들고 시작하면 해당 프로세스가 현재 파이썬 인터프리터의 "복제 된"복사본으로 실행됩니다. Process() 내에서 변수를 업데이트하는 것은 단지 그것을에서 업데이트되는 특정 프로세스에 로컬 변수를 업데이트합니다.

파이썬 프로세스간에 데이터를 공유하려면, 우리는 multiprocessing.Pipe()하는 multiprocessing.Queue()하는 multiprocessing.Value()하는 multiprocessing.Array() 또는 중 하나가 필요합니다 다른 다중 처리 안전 컨테이너.

import multiprocessing 

def worker(lock, counter, name): 
    with lock:   
     for i in range(10): 
      counter.value += 1 

     print "In process {}: {}".format(name, counter.value) 

def main(): 
    lock = multiprocessing.Lock()  
    counter = multiprocessing.Value('i', 0)   

    p1 = multiprocessing.Process(target=worker, args=(lock, counter, 1)) 
    p2 = multiprocessing.Process(target=worker, args=(lock, counter, 2)) 

    p1.start() 
    p2.start() 

    p1.join() 
    p2.join() 

    print "In main process: {}".format(counter.value) 

if __name__=='__main__': 
    main() 

이 저를 제공합니다 :

In process 1: 10 
In process 2: 20 
In main process: 20 

를 이제, 당신이 정말로 전역 변수를 사용하려는 경우, 당신은 multiprocessing.Manager()를 사용하지만, 내가 할 수 여기에

은 당신의 코드를 기반으로 한 예이다 첫 번째 방법이 바람직하다고 생각하고 이것은 "무거운"해결책입니다.

import multiprocessing 

manager = multiprocessing.Manager() 
counter = manager.Value('i', 0); 

def worker(lock, name): 
    global counter 

    with lock:   
     for i in range(10): 
      counter.value += 1 

     print "In process {}: {}".format(name, counter.value) 

def main(): 
    global counter 

    lock = multiprocessing.Lock()  

    p1 = multiprocessing.Process(target=worker, args=(lock, 1)) 
    p2 = multiprocessing.Process(target=worker, args=(lock, 2)) 

    p1.start() 
    p2.start() 

    p1.join() 
    p2.join() 

    print "In main process: {}".format(counter.value) 

if __name__=='__main__': 
    main() 
관련 문제