4

Python modules are initialized only when needed. Can you make use of this fact to share state amongst modules in this manner:

# a.py
import random
state = { 'foo' : random.random() } 

# b.py
from a import state 

# c.py
from a import state

Is it safe to assume that 'state' in b and c always refer to the same instance when b and c are running in the same process?

Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
smatting
  • 125
  • 6
  • BTW: what is your purpose for state sharing? There are legitimate reasons to do it, but in general this kind of thing is a bad idea. – Adrian Ratnapala Apr 05 '14 at 08:25
  • I've written a python library, which is used in different parts of an application. On import time the library reads some configuration that affects the behavior of some functions of the library. I need to be sure that I get the same behvaior everywhere. – smatting Apr 17 '14 at 13:00
  • That sounds reasonable. Although I don't particularly like libraries reading config files (unless ordered to do so by apps), sometimes it is the most practical approach. – Adrian Ratnapala Apr 17 '14 at 18:53

2 Answers2

4

To expand/clarify C1phr's answer:

state in the three modules will refer to the same object as long as neither a, b, nor c assigns a new value to state. If any of the three modules does state = <something else>, it will go out of sync. The modules can safely mutate the value (e.g., by doing state['blah'] = 'stuff'), just not assign a new value.

As C1phr says, you can guard against this by always referring to the variable via the module containing it, as a.state (from within b and c).

There are ways that one module could in theory be reloaded and thus unsync the variables, but these would be uncommon or undesirable. For instance, obviously if someone does reload(a) then a will be reloaded and b and c will not know about this. But this would be an unusual thing to do. Also, a module could be imported twice via different paths, which could make the variables seem to go out of sync if you didn't keep track of the two versions. But importing the same module twice in this way is pretty much always a mistake anyway.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
1

Since variables and functions are treated the same by Python on import, this will work, but the variables are copied into the new namespace. This is fine until you want to change the value of state, which will only be reflected in the namespace that you make the change in. If you want to have read and write access, you're best off with:

import a

Then access the variable with

MY_VAR = a.state

and set with

a.state = MY_NEW_STATE

See: https://stackoverflow.com/a/1086705/2047504

Community
  • 1
  • 1
c1phr
  • 590
  • 5
  • 14
  • 3
    "The variables are copied into the new namespace as read-only items" isn't really accurate. New variables are created in the new namespace pointing to the objects from the old namespace. You can set new values for these variables in the new namespace, but that won't affect the values of variables in the old namespace. (This is explained in the question you link to.) – BrenBarn Apr 05 '14 at 07:33
  • What I meant to ask is if there are circumstances where a.py might get reloaded which would result in creating a new instance of 'state'. I'm curious if the pattern above is idiomatic or if it's too risky to rely on it. – smatting Apr 05 '14 at 07:43
  • @smatting: it's safe. – Karoly Horvath Apr 05 '14 at 08:05
  • and to continue what @BrenBarn said, they aren't "read only" (immutable) either, e.g. you can `append` to a list. – Karoly Horvath Apr 05 '14 at 08:07
  • You're right, I was thinking read-only in the sense that changes made to state inside of b won't be applied to state in a, which I now realize that I worded in an awful manner. Thank you for pointing that out, I've corrected my answer. – c1phr Apr 05 '14 at 16:45