I will not provide a reproducible example, as for this specific problem I can not reproduce the problem with a small dummy example. Yet, I believe something weird happened, something which is not a simple typo/mistake on my side. Maybe this problem will ring a bell, and someone might have an explanation.
Let's consider 3 files of my project:
cli/main.py
main.py
nfb.py
In main.py
, a settings dictionary is loaded from a .json file. One of the specific value in this dictionary is settings = {'ONLINE':{'APPLY_REJECTION': True}}
. It then calls the main
function from the cli/main.py
file which argument is the settings dictionary.
main.py
from cli.main import main
settings = load_settings(fname)
main(settings)
As you might guess from the acronym CLI, the function called is a simple command-line interface where the user is provided with X possibilities (e.g. 9 with keys from 1 to 9) and based on the input, another function is called. The input phase is then repeated until an exit key, e.g. 0, is pressed.
cli/main.py
def main(settings):
while True:
selection = input_menu(options)
if selection == 0:
break # exit key
elif selection == 1
x, y = nfb.run(a, b, c, d, settings)
This is very schematic. Obviously in my code, there is error checking on the input, the variables are defined, ... One point to note however, the dictionary settings
is passed to the run function from the nfb.py
file.
In nfb.py
, the function run might modify the variable settings['ONLINE']['APPLY_REJECTION']
from True to False. Once, the function is exited and the program is waiting for a new user input (selection), as we have left the scope of nfb.run()
, the variable settings['ONLINE']['APPLY_REJECTION']
should be back to True for future nfb.run()
calls.
However, this is not what I observed. The variable settings['ONLINE']['APPLY_REJECTION']
stayed to False, outside the scope of nfb.run()
.
Even more surprising, I tried doing this in nfb.py
:
import copy
def run(a, b, c, d, settings):
backup_settings = copy.deepcopy(settings)
# do stuff
if condition:
settings['ONLINE']['APPLY_REJECTION'] = False
# restore settings
settings = backup_settings
With a few prints, I could confirm that before the # restore settings
, the variable settings['ONLINE']['APPLY_REJECTION']
was set to False, and after settings = backup_settings
, the last line of the function, the variable settings['ONLINE']['APPLY_REJECTION']
was set to True.
However, if in the while loop from the CLI I print the same variable before or right after the selection (i.e. user input), I could see that this variable remained set to False after being set to False once in the nfb.run()
function, and this despite the backup/restoration lines!
cli/main.py
def main(settings):
while True:
print (settings['ONLINE']['APPLY_REJECTION'])
selection = input_menu(options)
if selection == 0:
break # exit key
elif selection == 1
x, y = nfb.run(a, b, c, d, settings)
The above piece of code will print True the first time, and False once the variable has been set to False once by nfb.run()
.
To note, there is absolutely nowhere else where this variable is modified. Moreover, my solution to the problem was to extract the variable from the dictionary at the beginning of run
, and then work with this extract variable, thus avoiding to change anything from the settings dictionary.
Workaround:
def run(a, b, c, d, settings):
apply_rejection = settings['ONLINE']['APPLY_REJECTION']
# do stuff
if condition:
apply_rejection = False
This workaround works (nothing else was changed!) and shows that the modification applied to this variable settings['ONLINE']['APPLY_REJECTION']
was the one in nfb.run()
and that as I claim, there is no other line meddling with the setting dictionary directly anywhere.
Discussion:
It looks to me like in my initial approach, the settings
dictionary inside nfb.run()
pointed to the same object as to the one outside, loaded as parameter of the cli.main(settings)
function. Even more surprising, this link seemed to be broke as soon as the variable settings
inside nfb.run()
is re-assigned with a new value (in my case the deepcopy of the original object).
Does anyone who managed to follow this long post have an idea, an explanation, about this behavior?