[2016-08-25] Access shell script variables from python

In case you want to read bash variables from python, I have an example for you. The method is not safe, it will execute the shell script, so you have to trust the input! But the nice part is, that even calculated variables are returned.

Here the interesting part:

def load_config(config_filename):
    # to get the same set of env variables, we need to execute also multiple statements in one line
    default_env = check_output_shell("true;set").decode('utf8')

    config_data_list = open(config_filename).read().splitlines()
    config_data_list.append("set")
    # we join the lines with ; so the the BASH_EXECUTION_STRING will not contain newlines
    config_env_list = check_output_shell(";".join(config_data_list)).decode('utf8').splitlines()
    return dict(_get_dict_tuples(l) for l in config_env_list
                if l not in default_env and not l.startswith('BASH_EXECUTION_STRING'))

The key is, to append a set to the shell file and execute it and compare the output to an empty shell script with a set in it. Here is an example with string concatination:

$ cat input/string_concatenation.conf 
foo=bar
foo+=' baba'
$ python read-shell-vars.py input/string_concatenation.conf 
{'foo': 'bar baba'}

And one with a list concatination:

$ cat input/list_concatenation.conf 
lista=(a b c)
listb=(c d e)
listc=("${lista[@]}" "${listb[@]}")
$ python read-shell-vars.py input/list_concatenation.conf 
{'lista': ['a', 'b', 'c'],
 'listb': ['c', 'd', 'e'],
 'listc': ['a', 'b', 'c', 'c', 'd', 'e']}

This will only work for config like shell scripts that will not print to stdout. If you need to support this you need to redirect the output of both set commands to a file and read them.