TL;DR:
A separate process calls a function whenever data is available and provides that data as the input to the called function
In the function I process the data, and want to make results of it globally available (i.e., a globally available variable changes its value dynamically)
What is a clean method to achieve this across modules, when within a module, this job would be performed well through a global variable?
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:
- initialize an
eyetracker
object, pointing to the eyetracking device - "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:
eyetracker.py
where I define my callback functions and other eyetracking functionstest_eyetracker.py
where I import functions fromeyetracker.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.