3

I switch program mode by modifying a global value in my main module.

The change is reflected in following function calls originating inside that module, but not when other modules call the same functions.

Is the main module using an old/external/duplicated value when function calls come from the outside?

main_module.py

import second_module

mode = 1

def print_mode():
  print 'Mode: ' + str(mode)

if __name__ == "__main__":
  print_mode()
  mode = 2
  print_mode()
  second_module.problem()

second_module.py

from main_module import print_mode

def problem():
  print_mode()

output

$ python main_module.py
Mode: 1
Mode: 2
Mode: 1
fivecode
  • 35
  • 5

1 Answers1

2

The file you supply at the command line is executed as a module named __main__ (the __name__ == '__main__' condition is is relying on this). Modules are generally only imported once, future imports give another reference to the same module name.

However, this mechanism is based on the module name. from main_module import print_mode looks for a module named main_module, but there is no such module yet, so the file is loaded again and a separate module called main_module is created. This entails executing the code from main_module.py again, which again initializes mode = 1, but does fails the aforementioned condition and hence doesn't do anything else (such as mode = 2).

So you end up with three modules: __main__, second_module, and main_module. __main__.mode == 2, but main_module.mode == 1, and second_module.print_mode is main_module.print_mode, so the print_mode call in second_module refers to main_module.mode which is 2.

The easy way out is not having any logic in __main__: Put your entry point in a function main() in main_module.py, then create a separate script which doesn't do anything other than importing main_module and calling main_module.main(). Alternatively, don't use globals ;-)

  • Thanks, that solved it! Will keep `__main__` away from everything else hereafter. It would be nice to avoid global variables altogether, but I don't see how one could maintain a program mode/state. – fivecode May 26 '13 at 12:50
  • 1
    Another method is to, at the top of the file, add `if __name__ == '__main__': import main_module; main_module.main()` – Eric May 26 '13 at 13:46
  • Sounds like stopping during the import of `__main__` to import the same module again, and then continue. Would not that still give us three modules? – fivecode May 28 '13 at 16:01
  • 1
    @fivecode Yes, you'd get three modules, but avoid the problem of having any application state duplicated. This holds for all the approaches mentioned here. –  May 28 '13 at 16:08