2016-08-23 6 views
0

Ich bin bei Multiprocessing in ein seltsames Verhalten geraten.Multiprozessing sieht keine globalen Variablen?

Wenn ich versuche, eine globale Variable in einer Funktion zu verwenden, die von Multiprocessing aufgerufen wird, wird eine globale Variable nicht angezeigt.

Beispiel:

import multiprocessing 

def func(useless_variable): 
    print(variable) 

useless_list = [1,2,3,4,5,6] 
p = multiprocessing.Pool(processes=multiprocessing.cpu_count()) 
variable = "asd" 

func(useless_list) 

for x in p.imap_unordered(func, useless_list): 
    pass 

Ausgang:

asd 
multiprocessing.pool.RemoteTraceback: 
""" 
Traceback (most recent call last): 
    File "/usr/lib/python3.4/multiprocessing/pool.py", line 119, in worker 
    result = (True, func(*args, **kwds)) 
    File "pywork/asd.py", line 4, in func 
    print(variable) 
NameError: name 'variable' is not defined 
""" 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
    File "pywork/asd.py", line 11, in <module> 
    for x in p.imap_unordered(func, useless_list): 
    File "/usr/lib/python3.4/multiprocessing/pool.py", line 689, in next 
    raise value 
NameError: name 'variable' is not defined 

Wie Sie das erste Mal sehe ich einfach nur func es asd wie erwartet gedruckt nennen. Aber wenn ich die gleiche Funktion mit Multiprocessing anrufe, heißt es, dass die Variable variable nicht existiert, auch nachdem ich sie gerade vorher deutlich gedruckt habe.

Hört Multiprozessorverarbeitung globale Variablen? Wie kann ich das umgehen?

Antwort

1

multiprocessingPool s Gabel (oder spawn in einer Weise, die Forking auf Windows nachzuahmen) seine Worker-Prozesse in dem Moment der Pool erstellt wird. fork Der Elternspeicher wird in den untergeordneten Ordnern als Kopie-beim-Schreiben zugeordnet, es wird jedoch keine dauerhafte Verbindung zwischen ihnen hergestellt. Nach dem fork sind Änderungen, die im übergeordneten Element vorgenommen wurden, in den untergeordneten Elementen nicht sichtbar und umgekehrt. Sie können keine Variablen verwenden, die nach der Erstellung der Pool definiert wurden, und Änderungen an Variablen, die vor der Erstellung der Pool erstellt wurden, werden in den Workern nicht berücksichtigt.

In der Regel möchten Sie mit einem Pool veränderlichen globalen Zustand vollständig vermeiden; haben alle Daten an die Funktion übergeben Sie sind imap -ing (oder was auch immer) als Argumente (die serialisiert und an die Kinder gesendet, so dass der Zustand korrekt ist), und haben die Funktion return keine neuen Daten anstelle der Mutation Globals , die es serialisiert und es an den übergeordneten Prozess zurücksendet, um es so zu verwenden, wie es ihm passt.

Managers s sind eine Option, aber in der Regel nicht die richtige Option mit s; Normalerweise möchten Sie sich an die Mitarbeiter halten, die nur gelesene Globals betrachten, bevor die Pool erstellt wurde, oder mit Argumenten arbeiten und neue Werte zurückgeben, ohne den globalen Status zu verwenden.

1

Wenn Sie einen Prozess spammen, wird der gesamte Kontext kopiert, Sie müssen managers für den Austausch von Objekten zwischen ihnen verwenden, überprüfen Sie die official documentations, für die Verwaltung der Statusprüfung this.