I like this solution for small applications:
class App:
__conf = {
"username": "",
"password": "",
"MYSQL_PORT": 3306,
"MYSQL_DATABASE": 'mydb',
"MYSQL_DATABASE_TABLES": ['tb_users', 'tb_groups']
}
__setters = ["username", "password"]
@staticmethod
def config(name):
return App.__conf[name]
@staticmethod
def set(name, value):
if name in App.__setters:
App.__conf[name] = value
else:
raise NameError("Name not accepted in set() method")
And then usage is:
if __name__ == "__main__":
# from config import App
App.config("MYSQL_PORT") # return 3306
App.set("username", "hi") # set new username value
App.config("username") # return "hi"
App.set("MYSQL_PORT", "abc") # this raises NameError
.. you should like it because:
- uses class variables (no object to pass around/ no singleton required),
- uses encapsulated built-in types and looks like (is) a method call on
App
,
- has control over individual config immutability, mutable globals are the worst kind of globals.
- promotes conventional and well named access / readability in your source code
- is a simple class but enforces structured access, an alternative is to use
@property
, but that requires more variable handling code per item and is object-based.
- requires minimal changes to add new config items and set its mutability.
--Edit--:
For large applications, storing values in a YAML (i.e. properties) file and reading that in as immutable data is a better approach (i.e. blubb/ohaal's answer).
For small applications, this solution above is simpler.