JavaSa JavaSa - 3 months ago 10
Ruby Question

Ruby's ERB like feature in python

I've configuration files some formatted as

json
some formatted as
yaml
. I want to be able to read those configuration files with values which comes as environment variables. for example:

{"username":"Dan", "password":"<%= ENV['DB_PASSWORD']%>"}


Which means that password is retrieved when loading the json file from environment variable and replace the
<%= ENV['DB_PASSWORD']%>
with concrete value.

Note:1. The syntax mentioned above is like it is being used using ruby's erb only for illustration
2. I prefer a solution of native python without installing new python packages, but if there no such ,I'll accept this also.

Answer

What you are looking for is commonly called templating, and you have basically defined a template language.

Depending on what exactly you want to do, you can use the string.Template library from the stdlib. It only does simple variable substitutions, though, as opposed to ERb, which allows arbitrary code (including code that deletes all your data, formats your harddisk, starts a backdoor, …).

So, string.Template is both much less powerful than ERb, but also much safer. Your example already demonstrates this, as you cannot even access environment variables from within a template, you would have to pass them in explicitly.

This is the basic usage:

from string import Template

s = Template('{"username": "Dan", "password": "$db_password"}')

s.safe_substitute(db_password = 's00persekrit')
# >>> {"username": "Dan", "password": "s00persekrit"}

As accessing environment variables isn't possible inside the template, you will have to pass them in to the template explicitly:

from string import Template
from os import environ as env

s = Template('{"username": "Dan", "password": "$db_password"}')

s.safe_substitute(db_password = env['DB_PASSWORD'])
# >>> {"username": "Dan", "password": "s00persekrit"}

Actually, if you want to give the template access to all environment variables, you should be able to pass the os.environ dict directly (you can pass any dict-like object for the mapping).

from string import Template
from os import environ as env

s = Template('{"username": "Dan", "password": "$DB_PASSWORD"}')

s.safe_substitute(env)
# >>> {"username": "Dan", "password": "s00persekrit"}

If you want some more powerful substitutions, then you should look at some other so-called "logic-less" template languages (i.e. languages which only perform simple substitutions but don't allow executing code, and don't allow conditionals or loops). One of those languages is Mustache (the templating language used by GitHub), there are implementations in many languages, including Pystache for Python.

If you want / need more advanced features such as loops, conditionals, etc., you might need to look for more full-featured template languages such as Jinja.