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