Search code examples
pythondictionaryconfigurationpython-module

Dynamic entries in a settings module


I'm writing a package that imports audio files, processes them, plots them etc., for research purposes. At each stage of the pipeline, settings are pulled from a settings module as shown below.

I want to be able to update a global setting like MODEL_NAME and have it update in any dicts containing it too.

settings.py

MODEL_NAME = 'Test1'
DAT_DIR = 'dir1/dir2/'
PROCESSING = {
    "key1":{
        "subkey2":0,
        "subkey3":1
    },
    "key2":{
        "subkey3":MODEL_NAME
    }
}

run.py

import settings as s
wavs = import_wavs(s.DAT_DIR)
proc_wavs = proc_wavs(wavs,s.PROCESSING)

Some of the settings dicts I would like to contain MODEL_NAME, which works fine. The problem arises when I want to change MODEL_NAME during runtime. So if I do:

import settings as s
wavs = import_wavs(s.DAT_DIR)
s.MODEL_NAME='test1'
proc_wavs1 = proc_wavs(wavs,s.PROCESSING)
s.MODEL_NAME='test2'
proc_wavs2 = proc_wavs(wavs,s.PROCESSING)

But obviously both the calls so s.PROCESSING will contain the MODEL_NAME originally assigned in the settings file. What is the best way to have it update?

Possible solutions I've thought of:

  • Store the variables as a mutable type, then update it e.g.:

    s.MODEL_NAME[0] = ["test1"]
    # do processing things
    s.MODEL_NAME[0] = ["test2"]
    
  • Define each setting category as a function instead, so it is rerun on each call e.g.:

    MODEL_NAME = 'test1' ..
    
    def PROCESSING():
       return {
           "key1":{
               "subkey2":0,
               "subkey3":1
           },
           "key2":{
               "subkey3":MODEL_NAME
           }
       }
    

    Then

    s.MODEL_NAME='test1'
    proc_wavs1 = proc_wavs(wavs,s.PROCESSING())
    s.MODEL_NAME='test2'
    proc_wavs1 = proc_wavs(wavs,s.PROCESSING())
    

    I thought this would work great, but then it's very difficult to change any entries of the functions during runtime eg if I wanted to update the value of subkey2 and run something else.

Other thoughts maybe a class with an update method or something, does anyone have any better ideas?


Solution

  • You want to configure generic and specific settings structured in dictionaries for functions that perform waves analysis.

    Start by defining a settings class, like :

    class Settings :
    
      data_directory = 'path/to/waves'
    
      def __init__(self, model):         
         self.parameters= {
           "key1":{
               "subkey1":0,
               "subkey2":0
           },
           "key2":{
               "subkey1":model
           }
         }
    
    # create a new class based on model1
    s1 = Settings('model1')
    # attribute values to specific keys
    s1.parameters["key1"]["subkey1"] = 3.1415926
    s1.parameters["key1"]["subkey2"] = 42
    # an other based on model2
    s2 = Settings('model2')
    s2.parameters["key1"]["subkey1"] = 360
    s2.parameters["key1"]["subkey2"] = 1,618033989
    # load the audio
    wavs = openWaves(Settings.data_directory)
    # process with the given parameters
    results1 = processWaves(wavs,s1)
    results2 = processWaves(wavs,s2)