Import and execfile()

George Sakkis george.sakkis at gmail.com
Fri Jan 11 23:55:07 EST 2008


On Jan 11, 5:24 pm, Mike Meyer <mwm-keyword-python.b4b... at mired.org>
wrote:

> On Fri, 11 Jan 2008 14:05:11 -0800 (PST) George Sakkis <george.sak... at gmail.com> wrote:
>
> > I maintain a few configuration files in Python syntax (mainly nested
> > dicts of ints and strings) and use execfile() to read them back to
> > Python. This has been working great; it combines the convenience of
> > pickle with the readability of Python. So far each configuration is
> > contained in a single standalone file; different configurations are
> > completely separate files.
>
> You know, I've been there before. It's kinda neat, but not something
> you really want to put in the hands of most users.

Well, I am almost the only user (of the config file, not the
application) and the few others are developers too so that's not an
issue in this case.

> You can make the syntax cleaner by using classes to hold the values
> instead of nested dicts, etc. That way you don't have to quote the
> names of the values:
>
> class Foo:
>   bar = 1
>   baz = 2

Actually I am using the dict() constructor instead of literals so it's
as clean as with classes; IMO for nested options it's cleaner than
nested classes:

Env = dict(
    PORT = 6789,
    KEY = 123456789,
    EXE = '/usr/local/lib/myprog',
    LD_LIBRARY_PATH = ':'.join([
                                '/usr/lib',
                                '/usr/local/lib',
                               ]),
    OPTIONS = dict(
        n = None,
        min = 1,
        max = 15000,
    )
)


> > ======================
> > # some_config.py
>
> > # master_config.py is in the same directory as some_config.py
> > from master_config import *
>
> > # override non-default options
> > foo['bar']['baz] = 1
> > ...
>
> > ======================
> > # trying to set the configuration:
> > CFG = {}
> > execfile('path/to/some_config.py', CFG)
>
> > Traceback (most recent call last):
> > ...
> > ImportError: No module named master_config
>
> > I understand why this fails but I'm not sure how to tell execfile() to
> > set the path accordingly. Any ideas ?
>
> Manipulate sys.path yourself?

That's what Mitko suggested too, and indeed it works:

import sys, os

def setConfig(configfile):
    cfg = {}
    syspath = list(sys.path)
    try:
        sys.path.append(os.path.dirname(configfile))
        execfile(configfile, cfg)
    finally:
        sys.path = syspath
    return cfg


However this doesn't look very clean to me. Also it's not thread-safe;
guarding it explicitly with a lock would make it even less clean.
Ideally, I'd like to pass a new path to execfile without modifying the
original (even for the few milliseconds that execfile() wlll probably
take). With modules being singletons though, I don't think this is
possible, or is it ?

George



More information about the Python-list mailing list