Consider the following Python application of two files, namely app.py
:
#!/usr/bin/env python3
import other
MY_DICT = {'initial': 10}
def main():
print('before main:', MY_DICT)
MY_DICT['foo'] = 20
MY_DICT['bar'] = 30
print('after changes:', MY_DICT)
other.check_dict()
print('back in main:', MY_DICT)
if __name__ == '__main__':
main()
and other.py
:
def check_dict():
from app import MY_DICT
print('inside other:', MY_DICT)
I would like to make MY_DICT
from app.py
visible in other.py
. It is visible, but I cannot change it. Here is the output if I run ./app.py
with Python 3.8.0:
before main: {'initial': 10}
after changes: {'initial': 10, 'foo': 20, 'bar': 30}
inside other: {'initial': 10}
back in main: {'initial': 10, 'foo': 20, 'bar': 30}
Not only MY_DICT
is back to its initial state when inspected from other.py
, it's back to the changed state when I return to main.py
. What is happening here and how do I make it the a real global variable?
I've already read this question and ensured that I do re-import MY_DICT
in check_dict
.
Solution: don't do that. Do not import the entry point Python script as a module. Create a separate small file which is never imported by anyone else and is intended to be run from the shell.
When you run the app as ./app.py
Python actually loads your app.py
as a module named __main__
. But your other.py
says import app
, so it imports a separate module named app
, which is only coincidentally loaded from the same source file app.py
.
Now you have two instances of app.py
loaded in your program, each one having a separate MY_DICT
. Your __main__
module sees its own sys.modules['__main__'].MY_DICT
, but other
module accesses sys.modules['a'].MY_DICT
. You can check this by printing id(MY_DICT)
in both main()
and check_dict()
: they are different. See more details here.
Technically, you can import __main__ as app
in other.py
. However, that will break the moment someone tries to use other.py
in any other way which does not involve starting ./app.py
.