0

I am working on some legacy code and I will need to refresh some imported variable for another module. Eg.

module a:

# load from database
MAPPINGS = {...}

module b:

import a

def dowork():
    for key,value in a.MAPPINGS.iteritems():
        print key

module c:

# admin section
def manage_mapping():
    ....
    # refresh a.MAPPINGS

Lets assume a.MAPPINGS gets imported in other modules e, f, g etc, is it possible to reload module a.MAPPINGS and all other modules gets a new a.MAPPINGS?

Ref: I looked at this but it's more like refreshing in module b.

James Lin
  • 25,028
  • 36
  • 133
  • 233

1 Answers1

1

If things are structured exactly the way you've written your example in the question body (but not in your title), then for me in Python 2.7 a simple reload(a) in c.py works as you want:

# a.by
import time
MAPPINGS = {time.strftime('%Y-%m-%d %H:%M:%S'):''}


# b.py
import a
def dowork():
    for key,value in a.MAPPINGS.iteritems():
        print key


# c.py
import a
def manage_mapping():
    reload(a)

if __name__ == '__main__':
    import time
    from b import dowork
    dowork()
    time.sleep(2)
    manage_mapping()
    dowork()

If I do

$ python c.py

then I get:

2017-05-24 16:31:31
2017-05-24 16:31:33

which indicates c has successfully refreshed a.MAPPINGS from b's point of view.

Now, if b.py contained from a import MAPPINGS (as in your title) followed by a reference to MAPPINGS, instead of import a followed by a reference to a.MAPPINGS, then that's different:

# b.py
from a import MAPPINGS
def dowork():
    for key,value in MAPPINGS.iteritems():
        print key

In this case, b.py creates its own association between the name 'MAPPINGS' and the original dict created in module a. If a.py is re-run, it creates a new dict but module b still contains, and uses, its own reference to the old one. So now you'll get two timestamps the same. There are two potential fixes: (1) change to import a + a.MAPPINGS as above, instead of from a import MAPPINGS + MAPPINGS, or (2) move the import down into dowork() so the refreshed MAPPINGS is re-imported locally every time you want to use it:

# b.py
def dowork():
    from a import MAPPINGS
    for key,value in MAPPINGS.iteritems():
        print key

I would go with approach (1).

jez
  • 14,867
  • 5
  • 37
  • 64
  • Actually that's not true. I would go with approach (1) ***if*** you forced me to use `reload` as part of the solution, but on general principles of maintainability/comprehensibility I would avoid doing that in the first place. Instead I would make the process of refreshing-and-returning-`MAPPINGS` a function in module `a`. – jez May 24 '17 at 20:53