Python: Accessing YAML values using "dot notation"
<p>I'm using a YAML configuration file. So this is the code to load my config in Python:</p>

<pre><code>import os
import yaml
with open('./config.yml') as file:
    config = yaml.safe_load(file)
</code></pre>

<p>This code actually creates a dictionary. Now the problem is that in order to access the values I need to use tons of brackets.</p>

<p>YAML:</p>

<pre><code>mysql:
    user:
        pass: secret
</code></pre>

<p>Python:</p>

<pre><code>import os
import yaml
with open('./config.yml') as file:
    config = yaml.safe_load(file)
print(config['mysql']['user']['pass']) # &lt;--
</code></pre>

<p>I'd prefer something like that (dot notation):</p>

<pre><code>config('mysql.user.pass')
</code></pre>

<p>So, my idea is to utilize the PyStache render() interface.</p>

<pre><code>import os
import yaml
with open('./config.yml') as file:
    config = yaml.safe_load(file)

import pystache
def get_config_value( yml_path, config ):
    return pystache.render('{{' + yml_path + '}}', config)

get_config_value('mysql.user.pass', config)
</code></pre>

<p>Would that be a "good" solution? If not, what would be a better alternative?</p>

<p><strong>Additional question [Solved]</strong></p>

<p>I've decided to use Ilja EverilÃ¤'s solution. But now I've got an additional question: How would you create a wrapper Config class around DotConf?</p>

<p>The following code doesn't work but I hope you get the idea what I'm trying to do:</p>

<pre><code>class Config( DotDict ):
    def __init__( self ):
        with open('./config.yml') as file:
            DotDict.__init__(yaml.safe_load(file))

config = Config()
print(config.django.admin.user)
</code></pre>

<p>Error: </p>

<pre><code>AttributeError: 'super' object has no attribute '__getattr__'
</code></pre>

<p><strong>Solution</strong></p>

<p>You just need to pass <code>self</code> to the constructor of the super class.</p>

<pre><code>DotDict.__init__(self, yaml.safe_load(file))
</code></pre>

<p><strong>Even better soltution (Ilja EverilÃ¤)</strong></p>

<pre><code>super().__init__(yaml.safe_load(file))
</code></pre>

<p>I had the same problem a while ago and built this getter:</p>

<pre><code> def get(self, key):
    """Tries to find the configuration value for a given key.
    :param str key: Key in dot-notation (e.g. 'foo.lol').
    :return: The configuration value. None if no value was found.
    """
    try:
        return self.__lookup(self.config, key)
    except KeyError:
        return None

def __lookup(self, dct, key):
    """Checks dct recursive to find the value for key.
    Is used by get() interanlly.
    :param dict dct: The configuration dict.
    :param str key: The key we are looking for.
    :return: The configuration value.
    :raise KeyError: If the given key is not in the configuration dict.
    """
    if '.' in key:
        key, node = key.split('.', 1)
        return self.__lookup(dct[key], node)
    else:
        return dct[key]
</code></pre>

<p>The getter looks-up a config value from <code>self.config</code> in a recursive manner (by using <code>__lookup</code>).
If you have trouble adjusting this for your case, feel free to ask for further help.</p>

python python-3.x yaml