Generate config file from template using Python search and replace.

Peter Otten __peter__ at web.de
Sat Nov 28 18:07:53 EST 2015


Mr Zaug wrote:

> I need to generate a config file based on an existing "template" file. I
> need to replace a set of strings with other strings globally in the
> generated file.
> 
> Here is a snippet of the template file, where CONTENT_PATH and DAMPATH are
> two "placeholders" or variables. There are several other such
> placeholders.
> 
>       $include "_dispatcher_publish_filters.any"
>       /1000 { /type "allow"  /glob "* /CONTENT_PATH/*.html*" }
>       /1001 { /type "allow"  /glob "POST /DAMPATH/www/*.html *" }
> 
> The script's user will be asked to type in unique values when prompted for
> DAMPATH or CONTENT_PATH.
> 
> Since I know the variables themselves are not going to change (because the
> contents of the template file don't spontaneously change) should I be
> using regex to search for them or is there a better way? I was planning on
> using re.sub but I don't know whether that's the best way. Here's what my
> script looks like today.
> 
> from sys import argv
> import re
> from os.path import exists
> 
> script, template_file = argv
> print "Opening the template file..."
> 
> in_file = open(template_file)
> lines = in_file.readlines()
> 
> print "What is the serial number of the site?",
> _NNN = raw_input()
> 
> print "What is the brand, or product name?",
> _BRAND = raw_input()
> 
> print "What is the content path?",
> _CONTENT_PATH = raw_input()
> 
> out_file = open(_nnn + _brand + "_farm.any", 'w')
> 
> for line in lines:
>    re.sub('NNN', _NNN, line)
>    re.sub('BRAND, _BRAND', line)
>    re.sub('CONTENT_PATH', _CONTENT_PATH, line)
> 
> out_file.close()

There are many templating systems out there. Pick the one that suits you 
best. A very basic one is str.format():

>>> "{foo} {bar}".format(foo=1, bar=2)
'1 2'

Here's what your script might become if you choose that one:

$ cat interactive_template.txt
      $include "_dispatcher_publish_filters.any"
      /1000 {{ /type "allow"  /glob "* /{CONTENT_PATH}/*.html*" }}
      /1001 {{ /type "allow"  /glob "POST /{DAMPATH}/www/*.html *" }}
$ cat interactive_template.py

try:
    format_map = str.format_map
except AttributeError:  # python 2 compatibility
    import string

    def format_map(text, lookup):
        return string.Formatter().vformat(text, (), lookup)
    input = raw_input


class Lookup(dict):
    def __missing__(self, key):
        self[key] = value = input("{}: ".format(key))
        return value


def main():
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("template_file")
    parser.add_argument("generated_file", nargs="?")
    args = parser.parse_args()

    with open(args.template_file) as instream:
        template_text = instream.read()

    lookup = Lookup()
    generated_text = format_map(template_text, lookup)
    generated_file = args.generated_file
    if generated_file is None:
        generated_file = format_map("{nnn}{brand}_farm.any", lookup)
    print("Writing {}".format(generated_file))
    with open(generated_file, "w") as outstream:
        outstream.write(generated_text)


if __name__ == "__main__":
    main()
$ python interactive_template.py interactive_template.txt
CONTENT_PATH: foo
DAMPATH: bar
nnn: baz
brand: ham
Writing bazham_farm.any
$ cat bazham_farm.any 
      $include "_dispatcher_publish_filters.any"
      /1000 { /type "allow"  /glob "* /foo/*.html*" }
      /1001 { /type "allow"  /glob "POST /bar/www/*.html *" }





More information about the Python-list mailing list