2017-02-01 8 views
2

У меня есть конфигурационный файл config.py который содержит глобальную переменную, то есть в config.py у меня есть (5 по умолчанию)Глобальные переменные accross модули и темы в питона

# config.py 
globalVar = 5 

Теперь в модуле запуска .py Я устанавливаю глобальную переменную, а затем вызвать функцию печати:

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

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

Это хорошо работает (т.е. 7 печатается), но если я использую несколько потоков для печати (в test.py) он не работайте больше, то есть потоки не видят изменения, сделанные run.py (т.е. напечатано 5).

Как это можно решить?

+0

Что это даст вам вместо этого? –

+0

@CheynShmuel Он печатает 5 (по умолчанию). Поэтому я думаю, что потоки создают свою собственную копию config.py. – machinery

+0

Когда вы запускаете 'run.py' ?? –

ответ

3

Даже при работе в одной и той же теме у вас могут возникнуть проблемы с этим. Например, если вы делаете from config import globalVar вместо этого, если вы перекомпилируете globalVar в локальном модуле, он просто теряет ссылку на объект в конфигурационном модуле.

И даже если вы этого не сделаете, если изменения в переменной происходят во время импорта ваших различных модулей, очень сложно отслеживать фактический порядок импорта.

Когда вы добавляете потоки, это просто становится неуправляемым на 100% из-за всех видов условий гонки. Помимо состояния гонки (т. Е. Один из ваших потоков читает переменную до того, как она была установлена ​​в другом потоке) или неправильный импорт, потоки не должны влиять на видимость изменений глобальных переменных в том, как вы описываете.

Решение для детерминированного кода заключается в использовании структур данных, подходящих для обмена данными между потоками (и защиты данных по потокам).

Модуль сам threading предлагает Event объект, который вы можете использовать для одного потока не ждать наверняка пока другие изменения значения вы ожидаете:

config.py:

changed = Event() 
changed.clear() 

global_var = 5 

модуль в рабочей резьбе:

import config 

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

и по основной теме:

import config 

config.global_var = 7 
config.changed.set() # FRees the waiting Thread to run 

Обратите внимание, что в приведенном выше коде я всегда ссылаюсь на объекты в конфигурации с пунктирной нотацией. Это не имеет никакого значения для объекта «событие» - я мог бы делать from config import changed - так как я имею дело с внутренними состояниями одного и того же объекта, он будет работать, но если я сделаю from config import global_var и переназначаю его global_var = 7, это изменится только там, где имя local_var в контекстных точках текущего модуля. config.local_var все еще ссылается на исходное значение.

И так как вы на него, стоит взглянуть на queue module, а также на thread-local объектов

Когда она по-прежнему не работает

Еще одна возможность для не видя изменения в том, что , поскольку параллелизм не находится в вашем коде, но в другой библиотеке он порождает процессы с модулем multiprocessing вместо потоков.

Проблемы, которые возникли у вас, если вы ожидали Threads и имели многопроцессорные процессы, были именно тем, что вы описываете: изменений в глобальных переменных, которые не видны в других (просто потому, что каждый процесс имеет свои собственные переменные, конечно).

Если это так, возможно иметь (числовые, типизированные) объекты, которые синхронизированы в процессах. Проверьте классы Array and Value и multiprocessing Queue, чтобы иметь возможность отправлять и получать (в основном) произвольные объекты.

(Добавить import multiprocessing; print(multiprocessing.current_process()) в свой код, чтобы быть уверенными. Независимо от результата, пожалуйста, предложить сопровождающее RandomizedSearchCV документации упоминается явно, что они делают для параллельности)

+0

Спасибо за ваш ответ, но он не работает ... нет прогресса ... Потоки, похоже, создают новую копию конфигурации, а затем они ждут вечно сигнал продолжить ... Кстати, я использую RandomizedSearchCV, который порождает потоки. – machinery

+0

Я не упоминал об этом, но если ваше приложение использует «многопроцессорную» инстапцию «потоковой передачи», это именно то, что произойдет - хотя API-интерфейс, оба модуля идентичны. Вы уверены, что библиотека порождает потоки, а не подпроцессы? – jsbueno

+0

Ой из документации неясно, использует ли RandomizedSearchCV многопроцессорную обработку. Как решить проблему с помощью многопроцессорной обработки? – machinery

 Смежные вопросы

  • Нет связанных вопросов^_^