Reputation: 831
I want a single copy of var that behaves in a global way: i.e. its storage exists once and all references to it in both modules read and write the same storage. How can I get that behavior using two modules in total?
Here is my attempt, but it fails miserably:
# module1
#!python
import module2
var = 1
def touch_var():
global var
print(var, id(var))
var = 3
print(var, id(var))
def main():
global var
print(var, id(var))
var = 2
print(var, id(var))
module2.do_func()
print(var, id(var))
touch_var()
print(var, id(var))
if __name__ == '__main__':
main()
# module2
#!python
import module1
def do_func():
print(module1.var, id(module1.var))
module1.touch_var()
print(module1.var, id(module1.var))
module1.var = 4
print(module1.var, id(module1.var))
Output is:
1 17006627360
2 17006627392
1 17006627360
1 17006627360
3 17006627424
3 17006627424
4 17006627456
2 17006627392
2 17006627392
3 17006627424
3 17006627424
I have tried the same using assignment using mutable types:
#!python
import module2
var = [1]
def touch_var():
global var
print(var, id(var))
var = [3]
print(var, id(var))
def main():
global var
print(var, id(var))
var = [2]
print(var, id(var))
module2.do_func()
print(var, id(var))
touch_var()
print(var, id(var))
if __name__ == '__main__':
main()
#!python
import module1
def do_func():
print(module1.var, id(module1.var))
module1.touch_var()
print(module1.var, id(module1.var))
module1.var = [4]
print(module1.var, id(module1.var))
and I get this result:
[1] 7696579790600
[2] 7696579792072
[1] 7696579790664
[1] 7696579790664
[3] 7696579790600
[3] 7696579790600
[4] 7696579790664
[2] 7696579792072
[2] 7696579792072
[3] 7696579790600
[3] 7696579790600
And I've tried assigning to an element of a mutable type:
#!python
import module2
var = [1]
def touch_var():
global var
print(var, id(var))
var[0] = 3
print(var, id(var))
def main():
global var
print(var, id(var))
var[0] = 2
print(var, id(var))
module2.do_func()
print(var, id(var))
touch_var()
print(var, id(var))
if __name__ == '__main__':
main()
#!python
import module1
def do_func():
print(module1.var, id(module1.var))
module1.touch_var()
print(module1.var, id(module1.var))
module1.var[0] = 4
print(module1.var, id(module1.var))
And I get this result:
[1] 7696579790600
[2] 7696579790600
[1] 7696579790664
[1] 7696579790664
[3] 7696579790664
[3] 7696579790664
[4] 7696579790664
[2] 7696579790600
[2] 7696579790600
[3] 7696579790600
[3] 7696579790600
All three give the same result.
The output I want is this:
1
2
2
2
3
3
4
4
4
3
3
Why am I getting what I'm getting? How can I get what I want?
Note that this is NOT a duplicate of "Python: Sharing global variables between modules and classes therein", as @prune assumed, because in that one the answer was that the problem arose from using "from module import *", which I am not doing here; and the alternate answer was that the problem arose from using immutable types, which I have shown is not the problem. Also, one of my criteria is to solve this using two files, but that question uses three.
Upvotes: 1
Views: 52
Reputation: 120598
Here's a simple fix:
#!python
# module2
import __main__ as module1
The reason why your examples doesn't work as expected, is because the executed script is always added to sys.modules
as "__main__". So when you import it later using its file-name, you will get a reference to a different module object. In this regard, it is treated somewhat specially, since re-importing any other module will always refer to the same object in sys,modules
.
(NB: although the above fix solves your problem, it is usually considered bad practice).
Upvotes: 1
Reputation: 23079
Your problem comes from the fact that you have a circular import. You are running code in module1 to start. That creates one copy of the module1 namespace. You are then calling code in module2 from module1, where module2 imports module1 as well. Calling import module1
in module2 is creating a second copy of the module1 namespace.
That's why your first call in module2 prints 1
, because that's what its value is initially set to in module1.py
, and you've just imported that. All of the calls in module2, even those that call into module1, are working on this second copy of module1.
This is why, when you exit the call into module2 and are back in module1, your variable is back to a value of 2
, the value it was before you called into module2. Nothing has changed in the original copy of module1 by calling into module2, which was always operating on a the second copy of module1.
Here's a way to convince yourself this is happening. Make a copy of module1.py named module3.py and included that instead of module1.py in module2.py. You'll get exactly the same result, except now it will be clear what is going on as you wouldn't expect the var
in module1 and the one in module3 to be the same variable.
Upvotes: 2