1

I am currently have an global dictionary variable

_vars ={
   "key_1":"system environmental variable_1",
   "key_2":"system environmental variable_2",
   ................
   #around eight key pairs
}

The dictionary _vars will be initialized when the program runs by calling the initalize_vars function

def initialize_vars():
    var key in _vars:
        _vars[key] = os.path.expandvars(vars[key])

However, in the main function based on the number of arguments user provide, different functions will be called and some of them does not need to initialize the _vars (it will raise exception as the system environmental variable does not exist)

for example:

def A():
    initialize_vars()
    #do something
    return something

def B():
   #do something
   return something

def C():
   initialize_vars()
   #do something

def main(): if sys.argv[1]=="A": A() elif sys.argv[1] =="B": B() elif sys.argv[1] =="C": C()

So my question is: what is the best way to ensure that initialize_vars() does not called multiple times if it has been initialized already

card_master
  • 418
  • 3
  • 12

2 Answers2

1

I think you can add a global variable to store the initialize status of the dictionary, and when calling the method initialize_vars, you can decide whether the initialize is needed by checking the value of this global variable.

Sample code as below

vars_initialized = False
def initialize_vars():
    global vars_initialized
    if False == vars_initialized:
        var key in _vars:
            _vars[key] = os.path.expandvars(vars[key])
        vars_initialized = True
  • Attention: But please pay attention to lock and thread safe when you read / update value of this global variable, here is a scenario might happen:

    1. Code execution A run into the method initialize_vars and tries to initialize the var and is processing.
    2. Code execution B run into the method initialize_vars and got value of vars_initialized is False, also tried to initialize it.
    3. Code execution A finishes the initialization and set vars_initialized to True.
    4. Code execution B finishes the initialization and set vars_initialized to True also.

So you can see, the above code execution process is not correct, a correct one would be

  1. Code execution A run into the method initialize_vars and tries to initialize the var and is processing.
  2. Code execution B run into the method initialize_vars and find it's been initialized at that time, so it waits there until this process ends.
  3. Code execution A finishes the initialization and set vars_initialized to True.
  4. Code execution B got the status that vars_initialized is True and continues it's execution.

So here are another version of the code which might be better:

vars_initialized = False
vars_initialing  = False
def initialize_vars():
    global vars_initialized, vars_initialing
    vars_initialing = True
    if False == vars_initialized:
        var key in _vars:
            _vars[key] = os.path.expandvars(vars[key])
        vars_initialized = True
    vars_initialing = False

def A():
    if not vars_initialing:
        initialize_vars()
    else:
       while vars_initialing:
         //Wait for the init to be finished
          sleep(0.1) 
    #do something
    return something

def B():
   #do something
   return something

def C():
    if not vars_initialing:
        initialize_vars()
    else:
       while vars_initialing:
         //Wait for the init to be finished
          sleep(0.1) 
    #do something
    return something

def main():
    if sys.argv[1]=="A":
       A()
    elif sys.argv[1] =="B":
       B()
    elif sys.argv[1] =="C":
       C()

I am familiar with Java and we use an Object locker(synchronized) for this situation, I think something equality is needed for Python to make sure there's no conflict happens here, what I posted above is just a simulation for this locker.

Something called thread lock might be used here, here are some references.

Community
  • 1
  • 1
Lawrence Liu
  • 454
  • 3
  • 18
  • Is there any way to not use the global variable for tracking the status, or is it a good idea to add additional key value into the current _vars to track the status? – card_master Mar 21 '14 at 02:28
  • I don't think it's a good idea to add additional key value into the current _vars to track the status, any way status tracking is not part of the data itself, add it to the data will mess up data and program control logic, generally it's not an good idea. – Lawrence Liu Mar 21 '14 at 02:32
  • If we have a mechanism in Python to just lock the **initialize_vars** method and make sure only one possible execution at one time, that would be the best way, researching. – Lawrence Liu Mar 21 '14 at 02:35
  • Looks like you can use something called lock in python to do this, http://stackoverflow.com/questions/5185568/python-conditional-with-lock-design and http://docs.python.org/2.7/library/threading.html – Lawrence Liu Mar 21 '14 at 02:37
1

"Best"? Debatable. Probably the simplest:

initialized=False
def A():
    initialize_vars()
    #do something
    return something

def B():
   #do something
   return something

def C():
   initialize_vars()
   #do something

def initialize_vars():
   if not initialized:
      initialized = True
      for key in _vars:
         _vars[key] = os.path.expandvars(vars[key])

If you need to (and I suspect you might), you can keep track of the initialized state of each variable in a dictionary of booleans instead. That way only variables that haven't yet been initialized get initialized in the initialize_vars function

Mike Bell
  • 1,356
  • 11
  • 9
  • Is there any way to not use the global variable for tracking the status, or is it a good idea to add additional key value into the current _vars to track the status? – card_master Mar 21 '14 at 02:28
  • For the sake of avoiding name conflicts, I'd avoid adding the tracking variable to the _vars dict. If you're that uncomfortable with using a global flag, then you have a couple options. 1) put your A, B, C methods on an object and have a member on the object track the state of the initialization. Or 2) have the `initialized` variable and the `_vars` dict as two members of the same object, to the same effect. Really though, you're already using global variables in your _vars dict, so what's the big deal? Global variables aren't that taboo in Python because scripts get their own namespaces. – Mike Bell Mar 21 '14 at 02:35