S.A.
S.A.

Reputation: 2151

Access dynamically changing variable across modules

TL;DR:

Background

I use an eyetracking device (Tobii 4C) that can provide gaze data of a human via a Python API

The typical flow would be to:

  1. initialize an eyetracker object, pointing to the eyetracking device
  2. "subscribe" the eyetracker object to the actual data: eyetracker.subscribe_to(DATA, callback)

The callback is a function handle that gets called everytime the eyetracking device has new data available. Typically it would be used to save data, e.g.:

# `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)

The data recording would then run "in the background", until we cann eyetracker.unsubscribe()

However, to make use of "live" gaze data, one would have to make gaze_data a global variable, e.g.,

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

... now we can use gaze in our script, which gets continuously "updated" whenever the callback function is run (which happens at the sampling rate of the eyetracking device)

Problem

I have a larger project, where I organize 2 modules:

  1. eyetracker.py where I define my callback functions and other eyetracking functions
  2. test_eyetracker.py where I import functions from eyetracker.py and test them

However, when I import the functions from eyetracker.py into test_eyetracker.py, the global variable gaze is not being updated.

After a lot of search, I realized that this is because global variables are not cross-module. So when in test_eyetracker.py the gaze should be updated, this change is not available within the scope of test_eyetracker.py and as such, calls like assert gaze == 'value_i_know_it_should_be' evaluate as False.

Current solution

My current solution is, to define the eyetracking functions in the script, where I also use them. However, this does not feel clean , especially, because I would like to use the eyetracking functions in several other modules (not just the test module) = code duplication.

Is there a better way to organize this?

I have come across this post that shows how builtins are the only truly cross-module globals ... but it is discouraged to use those for a tweak that allows me a cross-module global variable.

Upvotes: 1

Views: 738

Answers (1)

sanyassh
sanyassh

Reputation: 8530

A workaround to this problem is to use for example a global dict. I will show you a code snippet based on the linked question that demonstrates the idea:

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

Upvotes: 2

Related Questions