Bridgeburners
Bridgeburners

Reputation: 657

How to re-import a dictionary object without a modification made in the current session?

Suppose I have the following module:

blah.py

a = 1
someDict = {'a' : 1, 'b': 2, 'c' : 3}

In the next python session I get the following:

>>> from blah import a, someDict
>>> a
1
>>> someDict
{'a': 1, 'b': 2, 'c': 3}
>>> a = 100
>>> someDict['a'] = 100
>>> del a, someDict
>>> from blah import a, someDict
>>> a
1
>>> someDict['a']
100
>>> import blah
>>> blah.someDict['a']
100

It appears that when I modify an object that I imported from another module, and then re-import that object, it recovers its original value expressed in the module. But this doesn't apply to values in a dictionary. If I want to recover the original value of someDict after making any modification, I have to close the current python session and open a new one. I find that this is even true if I merely called a function that modifies the dict elements.

Why does this happen? And is there some way I can re-import the dictionary with its original value without starting a new python session?

Upvotes: 0

Views: 122

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155403

Because you denamespaced the dict (with from x import y syntax), you need to do this as a two-step process (three including the necessary imports):

  1. Do import importlib, blah to gain access to the reload function, and the actual module to call it on
  2. Run importlib.reload(blah) to throw away the module cache of blah, and reread it afresh from disk (the fresh version is stored in the cache, so future imports related to blah see the new version)
  3. Run from blah import a, someDict again to pull the refreshed contents of blah

The reason you didn't see a problem with a is that after doing from blah import a, a wasn't special; __main__.a was just another alias to blah.a, but since a = 100 rebinds a to a completely new int anyway (and since ints are immutable, even a += 100 would actually perform a rebinding), you never changed blah.a (you'd have to explicitly do import blah, blah.a = 100 to have that happen).

someDict was a problem because, like a, __main__.someDict and blah.someDict end up as aliases of the same dict, and you mutate that dict, you're not rebinding __main__.someDict itself. If you want to avoid mutating blah's values in the first place, make sure the first modification to someDict rebinds it to a fresh dict, rather than modifying the one it's sharing with blah, e.g. instead of:

someDict['a'] = 100

do:

someDict = {**someDict, 'a': 100}

to make a fresh dict with a copy of blah.someDict, but with the value of 'a' in it replaced with a new value.

Upvotes: 4

Related Questions