[Solved] Access global variable across multiple modules and threads


The problem is that two instances of the variable X are created in such a set-up: one in a.py and another in b.py. The problem also occurs in this example that reduces it to the essence — it is not related to creating threads:

Problem in most simple form

File a.py:

X = "original value"
import b
if __name__ == '__main__':
    b.monitor()
    print ('A', X)

File b.py:

import a
def monitor():
    print ('B', a.X)
    a.X = "new value"
    print ('B', a.X)

When running a.py the output is:

B original value
B new value
A original value

If the same X were accessed, then the last line of the output would have read:

A new value

Explanation

This happens because import creates new instances of all global names therein. It will do this only upon the first time import a is encountered, and it really is the first time here. The module created by execution of a.py is named __main__, not a. Since this name is different from a, import a will really import the module, and not just reference the already loaded __main__ module. See also the Python documentation for a description of how module names are resolved.

As a consequence the names in these two modules are distinct; import a does not make the __main__ names accessible to the other module.

Solution

A quick solution is to replace the import a statement in b.py with an import __main__ statement, and use __main__.X as the qualified name you want to access in b.py. But this is not regarded the advised way to proceed.

A more robust way is to ensure the global variables are not defined in the executed script, but in an imported module — one that is imported by both a.py and b.py. The second import will make the names available that were defined when the first import was parsed:

File common.py:

X = "original value"

File a.py:

import common
import b
if __name__ == '__main__':
    b.monitor()
    print ('A', common.X)

File b.py:

import common
def monitor():
    print ('B', common.X)
    common.X = "new value"
    print ('B', common.X)

Now the output is:

B original value
B new value
A new value

Solution applied to your code

File common.py:

import time
X = {}
def set():
    global X
    X[time.time()] = 1

def get():
    global X
    return X

File a.py:

import common
import time
import b

if __name__ == '__main__':
    b.monitor()
    while True:
        time.sleep(1)
        common.set()

File b.py:

import common
import threading
import time

def f():
    while True:
        time.sleep(1)
        print common.get(), 'in b'

def monitor():
    t = threading.Thread(target=f)
    t.setDaemon(True)
    t.start()

2

solved Access global variable across multiple modules and threads