3

I'm writing a program that involves callbacks called from another module, and which need to access a global variable.
It seems that changes assigned to the global variable are not seen in the callback function, which only sees the original assignment. I'm guessing due to the import from the other module.
What is the proper way to write this pattern?

First module:

# a.py
from b import runb

myGlobal=None

def init():
    global myGlobal
    myGlobal=1

def callback():
    print myGlobal

def main():
    init()
    runb()

if __name__=='__main__':
    main()

Second module:

#b.py
def runb():
    from a import callback
    callback()

I would expect this program to print '1', but instead it prints 'None'

EDIT: init can only be called once (it is a simplification of a complex program)

2
  • You know it's best to avoid circular dependencies: stackoverflow.com/questions/1556387/… Commented May 19, 2014 at 13:29
  • @Scorpion_God: This link discusses dependencies between packages, not modules. I know it's best to avoid circular dependencies in general, but sometimes the alternatives are not that good. Commented May 19, 2014 at 14:06

4 Answers 4

6

Python imports the main module as __main__. When b.py imports a by its actual name, a new instance of the module is loaded under the name a. Each instance has its own myGlobal.

One solution is this:

#b.py
def runb():
    from __main__ import callback
    callback()

Another solution is to create a new main module. Import a there and make an explicit call to a.main().

Sign up to request clarification or add additional context in comments.

Comments

2

If you do this, "from a import callback", then again "myGlobal=None" will be executed, making it to print "None"

1 Comment

So can I define the global without any initialization? Will that do the trick? If so, how?
1

The main() function is not called when you import the file as a module. __name__ == "main" is true only when a.py is executed directly.

3 Comments

but I do run a.py directly
...which is not really true, I've confused it with the package's __init__.py script. Sorry
Assume a.py is the main module. I just run: python a.py
0

a.py

from b import *

def MyCallback(sText):
  global MyGlobalVar
  print("You can call this function from both modules: ", end="")
  print(sText + ", GlobalVar=" + str(MyGlobalVar))

RegisterMyCallback(MyCallback)

MyGlobalVar = 1
MyCallback("Called from a.py")

MyGlobalVar = 2
DoSomethingInModuleB()

b.py

def RegisterMyCallback(MyCallbackFunction):
    global MyCallback
    MyCallback = MyCallbackFunction

def DoSomethingInModuleB():
    MyCallback("Called from b.py")


Output:

$ python3 a.py
You can call this function from both modules: Called from a.py, GlobalVar=1
You can call this function from both modules: Called from b.py, GlobalVar=2

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.