34

I have an application consisting of a base app that brings in several modules. The base app reads a parameter file into a configuration hash, and I want to share it across all my modules.

Currently, I am passing a 'parent' object down to modules, and then those modules are doing stuff like self.parent.config to obtain the configuration.

However, as there are several levels to the module hierarchy, I find myself doing things like self.parent.parent.config, which is starting to look bad.

What are some better patterns for sharing a config object across an application and it's modules? I am thinking about having a 'config' module which basically creates a global config variable that can be set by the base app, then imported and accessed by other modules, but I am not sure if using globals like that is a bad practice for other reasons.

I am reasonably new to Python so be nice =)

aaa90210
  • 11,295
  • 13
  • 51
  • 88

4 Answers4

18

You could just:

import config

and have a global config module


excerpts from my comments:

You can always add special rules for odd situations by just saying oddValue if isOddSituation() else config.normalValue.

If you want to have configuration modules be hierarchically subclassable (like my other answer describes), then you can represent a config as a class, or you can use the copy module and make a shallow copy and modify it, or you can use a "config dictionary", e.g.:

import config as baseConfig
config = dict(baseConfig, overriddenValue=etc)

It doesn't really matter too much which scope you're in.

ninjagecko
  • 88,546
  • 24
  • 137
  • 145
  • 2
    This bothers me because I don't like Singletons all that much. I think there needs to be a bit more detail here. I would like to see a mechanism for easily 'pushing' a config onto a stack or something similar so you can easily replace the config or come up with special parsing rules for odd situations. – Omnifarious Apr 19 '11 at 02:45
  • What do you mean 'a stack' and 'parsing'? You can always add special rules for odd situations by just saying `oddValue if isOddSituation() else config.normalValue`. If you want to have configuration modules be hierarchically subclassable (like my other answer describes), then you can represent a config as a class, or you can use the `copy` module and make a shallow copy and modify it, or you can use a "config dictionary", e.g. `config = dict(baseConfig, overriddenValue=etc)` – ninjagecko Apr 19 '11 at 02:58
  • 1
    I think this is basically the answer I was after...validation that a global config module that is imported and accessed by other objects in the app as required is an OK approach to use. – aaa90210 Apr 19 '11 at 03:14
  • @S.Lott: Suppose, as a random example, you had a whole ton of code that needed the config values, and then you discovered that that code needed to run in an environment where at least some of those config values needed to be on a 'per-connection' basis. It would be nice to push the connection context onto the config stack when you were doing processing for that connection, then pop it back off again. And, of course, this means that it would be very nice to have generic config parsing code that dumped the result in an arbitrary object. – Omnifarious Apr 19 '11 at 03:58
  • 1
    Do evaluate the risks vs benefits of this setup if considering it as per https://stackoverflow.com/questions/40930663/config-file-with-a-py-file – ivan_pozdeev Apr 10 '18 at 17:39
10

Answering old question:

Just use dependency injection as suggested by @Reed Copsey here. E.g.

class MyClass:
    def __init__(self, myConfig):
        self.myConfig = myConfig
        ...

    def foo(self):
        self.myConfig.getConfig(key)
        ...
        self.myConfig.setConfig(key,val)
        ...

...
# myConfig is your configuration management Module/Class
obj = SomeClass(myConfig)
Community
  • 1
  • 1
Basel Shishani
  • 7,735
  • 6
  • 50
  • 67
0

I think by 'module', you are actually referring to a 'class/object'. An object is an instance of a class, for example:

class MyClass(object):
    def __init__(self, ...):
        ...
    ...

myObject = MyClass()

A module is a .py file you import, like so:

import mymodule

It seems unlikely that all the classes you instantiate would want to have access to a global configuration. However if you really need everything in your application to have access to some global parameters, you can put them in your own config module:

myParam1 = 1
myParam2 = 2

and then from any module or any object or anywhere really, as long as you did import config, you could just say print(config.myParam1)

Alternatively if you want a large hierarchy of objects to all share access to the same property, you don't need to refer to it via manually setting a self.parent. As long as you use inheritance, you can do stuff like:

class Parent(object):
    def __init__(self, theConfig):
        self.theConfig = theConfig

class Child(Parent):
    ...
    def method(self,...):
        print(self.theConfig)
ninjagecko
  • 88,546
  • 24
  • 137
  • 145
  • 1
    Yes, I meant objects instantiated from classes defined in various modules that are part of the overall app. I do use inheritance in the way you mention, but the issue relates to objects that have object that have objects...and I want objects at the bottom of this hierarchy to have access to the global configuration. – aaa90210 Apr 19 '11 at 03:11
  • why is it that the Parent/Child example does not solve your question? you no longer need to do super().theConfig (or I guess self.parent.theConfig, which is probably not what you want unless you're implementing a tree data structure or somesuch) – ninjagecko Apr 19 '11 at 03:15
  • I think I confused things by using the term 'parent'. I did not mean parent as in "child isa parent" but rather "parent has some children that need access to global config". – aaa90210 Apr 19 '11 at 03:56
-4

Take a look at this. It could help you: https://gist.github.com/dgarana/c052a3287629dd7c0b0c9d7921081e9d

David Garaña
  • 915
  • 6
  • 8
  • 5
    Please don't just post some tool or library as an answer. At least demonstrate [how it solves the problem](http://meta.stackoverflow.com/a/251605) in the answer itself. – Bugs Jul 14 '17 at 08:21