ConfigParser shootout, K.I.S.S. entry.

David Wilson dw at botanicus.net
Thu Oct 21 17:38:41 EDT 2004


On Thu, Oct 21, 2004 at 04:25:30PM -0500, Ian Bicking wrote:

> It's simplicity really seems like a combination of two things: (a) a
> simple INI file parser, (b) a multi-value dictionary.  With sections
> mixed in there somewhere as well.  I find sections to be a somewhat
> confusing metaphor -- should sections be their own object, or are
> configuration keys just parameterized (i.e., each key is really a
> tuple of (section, name))?

As per another posting to this thread, Microsoft-style INI files allow
multiple ordered values for the same 'key'. The parser works by creating
lists of (<key>, <value>) pairs for each configuration section. It is
left up to the user to decide whether these pairs should be represented as a
mapping (pass them through dict() and only the last seen key will remain
in the output), a list of (<key>, <value>) pairs (perhaps the reason why
you chose this module in the first place), or a set of string directives
of some description with a type attached, ie. the key.

    Example use #1:

        conf = ConfigParser(file('simple-app.conf'))

        kwargs = dict(conf.items('database'))
        module = kwargs.pop('_module')
        factory = kwargs.pop('_factory')

        db_module = __import__(module, globals(), locals(), [])
        db = getattr(db_module, factory)(**kwargs)

        ...


    Example use #2:

        for action, data in conf.items('setup-phase'):
            if action == 'assign':
                obj.assign(data)
            elif action == 'restrict':
                obj.restrict(data)


The ConfigParser could be considered a state machine who's state
reflects the contents of the last configuration file(s) loaded exported
via a set of methods and one short-hand notation (__getitem__).



> But that's really not so bad; whether those concerns are separated out 
> or not, I don't really mind either.  But one issue I see with this is 
> that it doesnt allow for very good error messages.  Because all the 
> parsing is done up-front, there's no information left about where 
> exactly the errors are located.  When you have large configuration 
> files, and cases where multiple configuration files are layered, or even 
> layering sections within a config file, it becomes important to provide 
> good error messages.

This module is designed to sit one layer below your input validation
routines. It would be a reasonable use to parse multiple configuration
files similarly to this:

    for pathname in config_pathnames:
        conf.clear()
        conf.load_file(file(pathname))
        my_application.config.load_and_validate(conf)

    ie. your configuration 'file I/O read' phase does not proceed to
    your next input until validation for the present step has succeeded.



> And then some minor nits: you don't check for the trailing ] on section 
> names (or strip whitespace), # isn't allowed for comments, and : isn't 
> allowed in place of =.  Also, line continuation isn't provided for.

I was concious of your first nit, but as a first draft I do not mind the
current behaviour. I do not strip whitespace at present as I have no
clear at-hand definition of either a) Microsoft's whitespace stripping
behaviour and b) Microsoft's comment-on-key-value-line stripping
strategy. I believe GetPrivateProfileString on win32 may also deal with
quotes.

Thanks for your review,


David.

-- 
Dance like you're not being watched,
Work like you don't need the money,
Fuck like you're on camera,
Love like you've never been hurt.



More information about the Python-list mailing list