문제

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

도움이 되었습니까?

해결책

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.

다른 팁

"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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top