I'm trying to allow a second module to modify the variables of the first in a circular import, but it doesn't seem to work.
I have 2 questions: 1) Why doesn't this work / what is the reasoning for this from a language development perspective and 2) are there any easy solutions that allow me to do the same thing perhaps in a slightly different way?
a.py:
import b
test1 = 'a'
test2 = None
test3 = '3'
if __name__ == '__main__':
print test1, test2, test3 #prints 'a', None, 3
b.changeVars()
print test1, test2, test3 #prints 'a', None, 3 (i.e. nothing has changed)
b.py:
import a
def changeVars():
print a.test1, a.test2, a.test3 #prints 'a', None, 3
a.test1 = 'NEW VAR 1'
a.test2 = 'NEW VAR 2'
a.test3 = 'NEW VAR 3'
print a.test1, a.test2, a.test3 #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'
What's happening is that when b.py tries to import a, there isn't an entry for it in sys.modules because the entry is under __main__. This causes the import mechanisms to re-import the module and place it under the name a. So now there is an a module and an entirely unrelated __main__ module. Changing b.py to something like this does the trick.
import sys
a = sys.modules['__main__']
def changeVars():
print a.test1, a.test2, a.test3 #prints 'a', None, 3
a.test1 = 'NEW VAR 1'
a.test2 = 'NEW VAR 2'
a.test3 = 'NEW VAR 3'
print a.test1, a.test2, a.test3 #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'
yields
aaron@aaron-laptop:~/code/tmp$ python a.py
a None 3
a None 3
NEW VAR 1 NEW VAR 2 NEW VAR 3
NEW VAR 1 NEW VAR 2 NEW VAR 3
aaron@aaron-laptop:~/code/tmp$
To get a better example of what's going on, consider these files:
#a.py
import b
import a
test = 'Foo'
if __name__ == '__main__':
print test #prints 'Foo'
b.changeVars()
print a.test, test # prints 'Foo', 'Bar'
and
#b.py
import a as a1
import sys
a2 = sys.modules['__main__']
def changeVars():
print a1.test, a2.test # Prints 'Foo', 'Foo'
a2.test = 'Bar'
print a1.test, a2.test # Prints 'Foo', 'Bar'
Which outputs
Foo
Foo Foo
Foo Bar
Foo Bar
This is clearly showing that sys.modules['a'] and sys.modules['__main__'] are referring to two different objects. The solution is probably to put the following as the first lines of a.py
import __main__ as a # due to Ignacio Vazquez-Abrams
Doing it this way allows for any other module to import a as well. On the whole though, I really don't see why you would want to do this. There's probably a better way to get this done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With