I have a module for configuration, projectConfig
, to parse a sample sheet for a project:
class SampleSheetFields():
FIELD_1 = "field1"
FIELD_2 = "field2"
class SampleSheetFieldsOld():
FIELD_1 = "field_1"
FIELD_2 = "field_2"
I had been using the first class in other modules like this:
from projectConfig import SampleSheetFields as ssFields
class SomeClass
def __init__(self):
...
check(someContent, ssFields.FIELD_1)
The thing is I had developed my software using the reference to ssFields
quite a lot. At some point new specifications said that the software should also use sample sheets with different field names. The quickest way I found to achieve that, without messing too much with the code, was to add the class SampleSheetFieldsOld
in the projectConfig
and to make a conditional import in my modules:
class SomeClass:
def __init__(self, useOld):
if useOld:
from projectConfig import SampleSheetFieldsOld as ssFields
else:
from projectConfig import SampleSheetFields as ssFields
...
check(someContent, ssFields.FIELD_1)
Note that the mandatory fields which are used have the same name so there is no conflicting or missing field. The program works as expected.
My questions are:
It's probably not the worst thing, but what I do find kind of problematic is the fact that you're now locked into two configuration options, old and new. What if you need to add a third or fourth etc. set someday? You won't be able to use a simple boolean test anymore.
Besides, it looks like your configuration options are all just simple string values, accessible via string keys. You don't need a class for that.
My suggestion is to forget about doing your configuration with the source code and use a configuration file. In your projectConfig
you can have a dict
which you initialize from a file, whose path/name can be provided on the command line or in whatever way is convenient. So projectConfig.py
might go something like this:
config_options = {}
def load_configuration(filename):
with open(filename) as f:
for line in f:
# get key and value
config_options[key] = value
Then everywhere you need to get a field name, just access projectConfig.config_options['field_key']
, e.g.
from projectConfig import config_options
class SomeClass
def __init__(self):
...
check(someContent, config_options['FIELD_1'])
Or use dict.get(key, default)
if there is a reasonable default value. This way, each time you need to switch to a different set of field names, you just create a new configuration file, and you don't have to touch the code.
Python's standard library includes a configparser
module which can handle the loading for you.