асинхронное поведение глобальной переменной с глобальными значениями внутри модуля в python

#python #global-variables

#python #глобальные переменные

Вопрос:

Итак, у меня есть модуль глобальных переменных global_var.py это выглядит следующим образом:

 x = 1
y = 2
  

Когда я хочу получить доступ ко всем этим переменным, я могу сделать что-то вроде этого:

 import global_var

# read var
print global_var.x
# change var
global_var.x = 0
  

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

 import global_var

global_var.x = 'new'
if global_var.x == 'new':
    print 'changed'
else:
    print 'not changed'
  

Описанная выше операция представляется вероятностной из-за асинхронности. Итак, что с этим, есть ли способ сделать такого рода вещи детерминированными, или мне просто не следует этого делать?


Хорошо, я нашел свою ошибку, python все еще работает и так же синхронен, как и прежде, все хорошо, спасибо всем за время и предложения.

Комментарии:

1. Можно с уверенностью предположить, что = оператор работает. Происходит что-то еще, может быть, у вас где-то есть циклический импорт?

2. Хм, что должно означать «вероятностный через асинхронность»? Какая бы проблема у вас ни возникла, в приведенном выше коде этого не произойдет…

3. «вероятностный через асинхронность» означает, что иногда это работает, иногда нет, и никакие другие параметры не меняются. Таким образом, поведение является вероятностным, и я предполагаю, что это связано с тем, что какая-то часть этого процесса является асинхронной.

4. Я понимаю все, что все говорят, и в целом согласен, но я вижу то, что вижу, и я уже проверил все простые вещи, на которые все указывают. Я буду продолжать предполагать, что это ненадежно, пока кто-нибудь не сможет действительно сказать мне, почему это надежно, а не утверждать, что это так.

5. Это надежно, потому что именно так это реализовано. Если у вас действительно есть пример, который другие люди могут использовать для воспроизведения поведения, которое вы описываете (итак, полный и желательно минимальный — см. sscce.org ) тогда, возможно, вы обнаружили ошибку, которую следует исправить. Однако, учитывая чрезвычайно простой и фундаментальный характер рассматриваемой функции — установка атрибута в модуле — маловероятно, что ошибка находится во время выполнения, но вместо этого находится в вашей программе. Если вы можете поделиться этим полным минимальным примером, то, возможно, кто-нибудь сможет точно указать, где это идет не так.

Ответ №1:

Описанное вами поведение — это не то, что когда-либо должно происходить, если вы просто делаете то, о чем вы сказали, что делаете. Дважды проверьте свой код, возможно, вы на самом деле не устанавливаете новое значение в определенных случаях, которые, как вам кажется, вы делаете; или, возможно, вы иногда читаете перед записью; или, может быть, у вас есть потоки, и точный порядок операций чтения и записи не является детерминированным. Если ваши глобальные переменные на самом деле находятся в вашем __main__ модуле (то есть в файле .py, который вы выполняете в командной строке), то, возможно, у вас есть две их копии (одна копия создается, когда файл .py превращается в __main__ модуль, потому что вы запустили его в командной строке; вторая копия создается, когда другой модуль импортирует его по его имени, создавая новый модуль с дублированной копией всего вашего кода и данных). В качестве очень маловероятной альтернативы, возможно, сбой памяти на вашем компьютере приводит к неправильному, непредсказуемому поведению.

Установка атрибута всегда устанавливает его (или, по крайней мере, вызывает специальный метод, который отвечает за его установку — вы могли бы переопределить этот специальный метод, чтобы по какой-то причине не устанавливать его, но тогда это ваша вина. 🙂

Помимо этого, использование подобных «модулей глобальной переменной» — плохая идея, если вы хотите создать понятное, поддерживаемое, тестируемое (работающее) программное обеспечение. Это своего рода «жуткое действие на расстоянии». Кто знает, на какие другие части вашей программы вы будете влиять всякий раз, когда вы устанавливаете одну из этих переменных. Вместо этого шаблона передавайте аргументы каждой функции. Сделайте так, чтобы сигнатура каждой функции включала все состояния, которые ей необходимы для выполнения своей работы. Если у вас много состояний и вам не нравятся длинные сигнатуры аргументов, тогда подумайте о создании объектов для хранения этого состояния и добавлении методов к этим объектам.