I have created a .ini-like file with all the values which I need later in my program, see below:
[debugging]
checkForAbort = 10
...
[official]
checkForAbort
self.name = value doesn't work as you expect. You might mean setattr(self, name, value) It creates instance attributes dynamicallly.
To make it a singleton you could make the instance to be a global variable in config/settings module. Initialize it once on a program startup e.g., like the logging module does it for the root logger: logging.config.fileConfig('logging.conf').
It is a common desire to use an attribute access for what is essentially a dict e.g., argparse.Namespace that carries command-line options.
You could access the config later by importing it: from mypackage.config import config, e.g., mypackage/config.py:
class Config(object):
...
config = Config() # empty or default config without any configuration
In mypackage/__main__.py:
from .config import config
...
# initialization code
config.update_from_file('mypackage.conf') # it might call `setattr()` inside
Note: setattr() works correctly even you set properties. __dict__.update() breaks in this case:
class XValidatorMixin(object):
@property
def x(self):
return self._x
@x.setter
def x(self, value):
if value < 0:
raise ValueError
self._x = value
class CUpdate(XValidatorMixin):
def __init__(self, **options):
self.__dict__.update(options)
class CSetAttr(XValidatorMixin):
def __init__(self, **options):
for name, value in options.items():
setattr(self, name, value)
for C in [CUpdate, CSetAttr]:
o = C(a=1, b=2) # non-property attributes work as expected
assert o.a == 1 and o.b == 2
o = CSetAttr(x=1)
assert o.x == 1 # setattr also sets property
o = CUpdate(x=1)
try:
o.x # .update() doesn't set property
except AttributeError:
pass
else:
assert 0
try:
o = CSetAttr(x=-1) # invokes property setter
except ValueError: # that correctly reject negative values
pass
else:
assert 0