потоки Python с глобальными переменными - PullRequest
0 голосов
/ 20 января 2011

Я столкнулся с проблемой при написании кода потоков Python, когда я написал несколько рабочих потоков классов, все они импортируют глобальный файл, например sharevar.py, мне нужна переменная вроде regdevid отслеживание регистрационного идентификатора устройства, затем, когда один поток изменяет его значение, тогда другие потоки могут получить его свежим, но результат таков: когда один поток меняет свое значение, другие по-прежнему получают значение по умолчанию, которое я определил в файле sharevar.py, почему? со мной что-то не так?

# thread a
from UserShare import RegDevID
import threading
class AddPosClass(threading.Thread):
global commands
# We need a pubic sock, list to store the request
def __init__(self, queue):
    threading.Thread.__init__(self)
    self.queue = queue

def run(self):
    while True:
        data = self.queue.get()
        #print data
        RegDevID = data
        #print data
        send_queue.put(data)
        self.queue.task_done()
# thread b
import threading
from ShareVar import send_queue, RegDevID 
"""
AddPos -- add pos info on the tail of the reply
"""
class GetPosClass(threading.Thread):
    global commands
    # We need a pubic sock, list to store the request
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        while True:
            data = self.queue.get()
            #print data
            data = RegDevID
            #print data
            send_queue.put(data)
            self.queue.task_done()
# ShareVar.py
RegDevID = '100'

Вот и все, когда поток a изменил RegDevID, поток b все еще получает значение по умолчанию. Большое спасибо.

    from ShareVar import RegDevID

class Test():
    def __init__(self):
        pass
    def SetVar(self):
        RegDevID = 999
    def GetVar(self):
        print RegDevID

if __name__ == '__main__':
    test = Test();
    test.SetVar()
    test.GetVar()

ShareVar.py:

RegDevID = 100

Результат:

100

почему

Ответы [ 2 ]

6 голосов
/ 20 января 2011

Полагаю, вы пытаетесь получить доступ к общей переменной без lock. Если вы не получите блокировку и не попытаетесь прочитать общую переменную в одном потоке, когда другой поток записывает в него, значение может быть неопределенным.

Для исправления убедитесь, что вы приобрели блокировку в потоке перед чтением или записью в него.

import threading

# shared lock: define outside threading class
lock = threading.RLock()
# inside threading classes...
# write with lock
with lock: #(python 2.5+)
    shared_var += 1
# or read with lock
with lock:
    print shared_var

Читать о Поток Python .

Ответьте на нижнюю проблему с областью видимости:

В нижнем образце у вас возникла проблема с областью видимости. В SetVar() вы создаете метку RegDevID, локальную для функции. В GetVar() вы пытаетесь прочитать с метки RegDevID, но она не определена. Таким образом, он выглядит выше по объему и находит тот, который определен в импорте. Переменные должны находиться в одной области видимости, если вы хотите, чтобы они ссылались на одни и те же данные.

Хотя области действия определяются статически, они используются динамически. В любое время во время исполнения как минимум три вложенные области пространства имен доступны напрямую:

самая внутренняя область, которая ищется первой, содержит локальные имена объемы любых включающих функций, которые ищутся, начиная с ближайшей ограждающей областью, содержит нелокальные, но также неглобальные имена следующая за последней область содержит глобальные имена текущего модуля самая внешняя область (последняя) - это пространство имен, содержащее встроенные имена

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

Читайте о области видимости .

3 голосов
/ 20 января 2011

Вы уверены, что разместили свой фактический код? Вы импортировали RegDevID из двух разных модулей:

# thread a
from UserShare import RegDevID

против

# thread b
from ShareVar import send_queue, RegDevID 

В любом случае, ваш проблам не имеет ничего общего с потоками. Думайте о 'from somemodule import somevar' как о выражении присваивания. Примерно эквивалентно некоторой магии для загрузки модуля, если он еще не загружен, за которым следует:

somevar = sys.modules['somemodule'].somevar

Когда вы импортируете RegDevID из другого модуля, вы создаете новое имя в текущем модуле. Если вы мутируете объект, то другие пользователи объекта увидят изменения, но если вы перепривязаете имя в этом модуле, то это повлияет только на локальное имя, это ничего не изменит в исходном модуле.

Вместо этого вам нужно перепривязать переменную в другом модуле:

import ShareVar
...
ShareVar.RegDevID = data

За исключением, конечно, вы почувствуете себя намного лучше, если создадите класс для управления своим общим состоянием.

Ваш второй бит кода просто неправильно понимает локальные и глобальные переменные:

def SetVar(self):
    RegDevID = 999

внутри функции вы создали новую локальную переменную RegDevID, которая не имеет ничего общего с глобальной переменной с тем же именем. Используйте оператор global, если вы хотите привязать глобальную переменную:

def SetVar(self):
    global RegDevID
    RegDevID = 999
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...