2016-07-13 9 views
1

Ich habe gerade Python Multiprocessing für das Lesen der Datei oder eine globale Variable getestet, aber es ist etwas seltsam passieren.Etwas seltsames passiert mit Python Multiprozess

Um zB:

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() 

Das Programm lesen eine globale Variable, aber die Ausgabe ist:

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

Es scheint, dass der Unterprozess nicht richtig die globale Variable erhalten und bearbeiten können. Wenn ich das Programm zum Lesen der Datei ändere, liest jeder Unterprozess die Datei vollständig und ignoriert die Sperre.

Also, wie passieren diese? Und wie löst man dieses Problem?

+0

Ich glaube, dass Sie den globalen Zustand mit einem 'multiprocessing.Manager' müssen verwalten – mgilson

+0

Sie verwenden könnten Multithreading statt Multiprocessing für die gleichzeitige Ausführung. Alle Threads sind Teil eines einzelnen Prozesses. – VPfB

Antwort

1

Globale Variablen werden nicht zwischen Prozessen aufgeteilt. Wenn Sie einen neuen Process() erstellen und starten, wird dieser Prozess in einer separaten "geklonten" Kopie des aktuellen Python-Interpreters ausgeführt. Aktualisieren der Variable innerhalb eines Process() wird nur die Variable aktualisiert werden lokal auf den jeweiligen Prozess in aktualisiert.

Um Daten zwischen Python Prozesse gemeinsam nutzen, brauchen wir ein multiprocessing.Pipe(), ein multiprocessing.Queue(), ein multiprocessing.Value(), ein multiprocessing.Array() oder eine der andere Multiprocessing-sichere Container.

Hier ist ein Beispiel auf dem Code basiert:

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() 

Das gibt mir:

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

Nun, wenn Sie wirklich eine globale Variable verwenden möchten, können Sie einen multiprocessing.Manager() verwenden können, aber ich denke, die erste Methode ist vorzuziehen, und dies ist eine "schwerere" Lösung. Hier ein Beispiel:

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()