Доступ к динамически изменяемой переменной в разных модулях - PullRequest
1 голос
/ 20 мая 2019

TL; DR:

  • Отдельный процесс вызывает функцию всякий раз, когда доступны данные, и предоставляет эти данные в качестве входных данных для вызываемой функции

  • В функции я обрабатываю данные и хочу сделать их результаты доступными глобально (т. Е. Глобально доступная переменная динамически меняет свое значение)

  • Что такое чистый метод для достижения этой цели во всех модулях, если в модуле это задание будет хорошо выполняться через глобальную переменную?

Фон

Я использую устройство для слежения за глазами (Tobii 4C), которое может предоставлять данные о человеке через Python API

Типичный поток будет:

  1. инициализировать eyetracker объект, указывающий на устройство отслеживания движений глаз
  2. «подписать» объект eyetracker на фактические данные: eyetracker.subscribe_to(DATA, callback)

callback - это дескриптор функции, который вызывается каждый раз, когда на устройстве отслеживания движений появляются новые данные. Обычно это используется для сохранения данных, например:

# `gaze_data` is what gets returned from the eyetracking device that we subscribed to
def my_callback(gaze_data):
    # fname is defined globally in this case
    with open(fname, 'a') as f:
        f.write(gaze_data)

Запись данных будет выполняться "в фоновом режиме", пока мы не сможем eyetracker.unsubscribe()

Однако, чтобы использовать «живые» данные взгляда, нужно сделать gaze_data глобальной переменной, например,

def my_callback(gaze_data):
    global gaze
    gaze = gaze_data['gaze_point']

... теперь мы можем использовать gaze в нашем скрипте, который постоянно «обновляется» при каждом запуске функции обратного вызова (что происходит с частотой дискретизации устройства отслеживания движений)

Проблема

У меня есть крупный проект, в котором я организую 2 модуля:

  1. eyetracker.py где я определяю свои функции обратного вызова и другие функции отслеживания движения глаз
  2. test_eyetracker.py, куда я импортирую функции из eyetracker.py и проверяю их

Однако, когда я импортирую функции из eyetracker.py в test_eyetracker.py, глобальная переменная gaze не обновляется.

После долгих поисков я понял, что это потому, что глобальные переменные не являются кросс-модульными . Поэтому, когда в test_eyetracker.py необходимо обновить gaze, это изменение недоступно в пределах test_eyetracker.py, и поэтому вызовы типа assert gaze == 'value_i_know_it_should_be' оцениваются как False.

Текущее решение

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

Есть ли лучший способ организовать это?

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

1 Ответ

1 голос
/ 20 мая 2019

Обходной путь к этой проблеме - использовать, например, глобальный диктат.Я покажу вам фрагмент кода, основанный на связанном вопросе, который демонстрирует идею:

file1.py:

global_dict = {'x': 5}
x = 5 # for comparison

file2.py:

from file1 import *

def update_x():
    global x
    global global_dict
    x += 1
    global_dict['x'] += 1

main.py:

from file2 import *

update_x()
print(x) # 5
print(global_dict['x']) # 6
...