Search code examples
pythonscopeglobal-variables

Python global variable instantiated twice


In my project, I am trying to share a global variable across modules as described in the Python documentation: https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules

I seemed to find, however, that the global variable is instantiated twice and I am not sure why. I want the variable to be a singleton.

I was able to reproduce the issue with this minimal example:

# main.py
class TheClass:
    def __init__(self):
        print("init TheClass")

    def do_work(self):
        import worker
        worker.do_work()

the_class:TheClass = TheClass()

if __name__ == '__main__':
    the_class.do_work()
# worker.py
from main import the_class

def do_work():
    print("doing work...")

Output of python main.py:

init TheClass
init TheClass
doing work...

'init TheClass' is logged twice which implies that the class was instantiated twice.

I was unable to reproduce this behaviour in the interactive Python shell:

Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import main
init TheClass
>>> main.the_class.do_work()
doing work...
>>>

How do I fix this undesired behaviour?


Solution

  • This happens because you are having a circular import and because of something special that happens with the codefile that you are actually starting.

    If you start a file (as the argument to python) it will become the __main__ module independent of its filename. If at a later point in time the same file is imported, it is not recognized as already imported and is reimported under its real name, main in your case. This is why the code is run twice. A third import will not rerun the code.

    You can fix it by preventing circular imports (don't put stuff to import into the starter), or by putting the code that should not run twice into the name checking if you already have.