2017-02-01 3 views
2

ich eine Konfigurationsdatei config.py haben, die eine globale Variable gilt, dh in config.py Ich habe (5 ist die Standardeinstellung)Globale Variablen accross Module und Threads in Python

# config.py 
globalVar = 5 

nun in einem Modul Lauf Py ich gründe die globale Variable und dann nenne ich eine Druckfunktion:

# run.py 
import config 
import test 
config.globalVar = 7 
test.do_printing() 

# test.py 
import config 
def do_printing(): 
    print(config.globalVar) 

das funktioniert gut (dh 7 gedruckt wird), aber wenn ich mehrere Threads zum Drucken verwenden (in test.py) es nicht der Fall ist arbeite nicht mehr, dh dann sehen die Threads die Änderung von run.py nicht mehr (dh 5 wird gedruckt).

Wie kann das gelöst werden?

+0

Was es Ihnen nicht geben statt? –

+0

@CheynShmuel Es druckt 5 (Standard). Also denke ich, dass die Threads ihre eigene Kopie von config.py erstellen. – machinery

+0

Wann starten Sie 'run.py' ?? –

Antwort

3

Auch wenn Sie mit demselben Thread arbeiten, könnten Sie Probleme haben. Wenn Sie beispielsweise from config import globalVar ausführen, wenn Sie die globale Variable im lokalen Modul erneut binden, verliert sie nur den Verweis auf das Objekt im Konfigurationsmodul.

Und selbst wenn Sie das nicht tun, wenn Änderungen an der Variablen zum Zeitpunkt des Imports Ihrer verschiedenen Module stattfinden, ist es sehr schwer, den tatsächlichen Importauftrag zu verfolgen.

Wenn du Threads hinzufügst, wird das wegen aller Arten von Rennbedingungen einfach zu 100% unbeherrschbar. Anders als eine Race-Bedingung (d. H. Einer Ihrer Threads liest die Variable, bevor sie für den anderen Thread festgelegt wurde) oder fehlerhafter Import sollten Threads die Sichtbarkeit globaler Variablenänderungen nicht in der Art und Weise beeinflussen, wie Sie sie beschreiben.

Die Lösung für deterministischen Code ist die Verwendung von Datenstrukturen, die für diesen Austausch über Threads (und Datensicherung über Threads) geeignet sind.

Das threading Modul selbst bietet das Event Objekt, das Sie für einen Thread verwenden können sicher, bis die anderen Änderungen um den Wert warten Sie erwarten:

config.py:

changed = Event() 
changed.clear() 

global_var = 5 

Modul in Worker-Thread:

import config 

def do_things(): 
    while True: 
     config.changed.wait() # blocks until other thread sets the event 
     do_more_things_with(config.global_var) 

und auf den Haupt-Thread:

Hinweis im obigen Code, ich beziehe mich immer auf die Objekte in Config mit der gepunkteten Notation. Das macht keinen Unterschied für das "Ereignis" -Objekt - ich könnte from config import changed tun - da ich mit internen Zuständen des gleichen Objekts zu tun habe, würde es funktionieren - aber wenn ich from config import global_var mache und es mit global_var = 7 neu zuweisen, ändert sich das nur wo der local_var Name im Kontext des aktuellen Moduls. Die config.local_var verweist immer noch auf den ursprünglichen Wert.

Und da man es sind, lohnt es sich einen Blick auf die queue module sowie auf thread-local Objekte

Wenn es immer noch nicht funktioniert

Eine andere Möglichkeit, nicht zu sehen, die Veränderungen, die ist, dass Da die Parallelität nicht in Ihrem Code, sondern in einer anderen Bibliothek ist, erzeugt sie Prozesse mit dem multiprocessing Modul anstelle von Threads.Die Probleme, die Sie hatten, wenn Sie Threads erwarteten und Prozesse, die von mehreren Prozessen stammten, wären genau das, was Sie beschreiben: Änderungen an globalen Variablen, die in anderen nicht sichtbar sind (weil jeder Prozess natürlich seine eigenen Variablen hat).

Wenn dies der Fall ist, können Objekte (numerisch, typisiert) über die Prozesse hinweg synchronisiert werden. Überprüfen Sie die Klassen Array and Value und multiprocessing Queue, um (meist) beliebige Objekte senden und empfangen zu können.

(Add import multiprocessing; print(multiprocessing.current_process()) Linie, um Ihren Code sicher sein. Unabhängig von dem Ergebnis finden Sie in die Maintainer von RandomizedSearchCV Dokumentation deuten darauf hin, ausdrücklich zu erwähnen, was sie für Parallelität tun)

+0

Danke für Ihre Antwort, aber es funktioniert nicht ... es gibt keinen Fortschritt ... Die Threads scheinen eine neue Kopie der Config zu erstellen und dann warten sie ewig das Signal zum Fortfahren ... Nebenbei verwende ich RandomizedSearchCV, das die Threads hervorbringt. – machinery

+0

Ich habe es nicht erwähnt, aber wenn Ihre Anwendung "Multiprocessing" anstelle von "Threading" verwendet, ist genau das was passieren würde - obwohl, API, beide Module identisch sind. Sind Sie sicher, dass die Bibliothek Threads und keine Subprozesse erzeugt? – jsbueno

+0

Oh von der Dokumentation ist es nicht klar, wenn RandomizedSearchCV Multiprocessing verwendet. Wie könnte das Problem mit Multiprocessing gelöst werden? – machinery