more on config imports

In a previous post I mentioned importing a python file as a config file via ihooks.

Craig Ringer sent me a note, pasted below

I think there's a considerably simpler approach than the one you've taken, as well as an alternative to ihooks that's quite a bit tidier to use.

First, the simple alternative. The `import' statement pretty much just calls __builtin__.__import__(), and you're quite free to use that in your code directly. This lets you do something like this for your config importer (based off your posted code):

    import os
    import __builtin__

    try:
        config = __builtin__.__import__('config', globals(), {}, [])
    except Exception:
        # We catch any Exception because the user could do all sorts
        # of things wrong in the import. We can't even guarantee that
        # an ImportError comes from our __import__ call and not an import
        # attempt inside the config file without delving into the backtrace
        # using the traceback module.
        print "An error occurred while importing the config file."
        print "Traceback follows."
        raise

    def config_example():
        print config.some_config_dictionary["option"]

    if __name__ == "__main__":
            config_example()

It's worth noting that if I recall correctly the \_\_builtin\_\_
should be used; \_\_builtins\_\_ is specific to the CPython
implementation.

If you start having to accept an explicit path for the config file
from the user or something then ihooks is probably better. For
simple cases, \_\_builtin\_\_.\_\_import\_\_() is much quicker and
easier to understand though.

If you do decide you need more than \_\_builtin\_\_.\_\_import\_\_()
has to offer, it may be better to look into the PEP 302 import
hooks, which are much cleaner and simpler than the rather ancient
ihooks module. I should probably submit a patch to the ihook docs to
make them refer to PEP 302, actually.

Some info on PEP 302:
`http://www.python.org/doc/2.3.5/whatsnew/section-pep302.html <http://www.python.org/doc/2.3.5/whatsnew/section-pep302.html>`__

Indeed, __import__ was my first attempt at doing what I wanted; but it is a little off the semantics I wanted. I wanted to be able to specify a file on the command line with an argument --config=/path/to/file/config.py and have that loaded in. For example, __import__("/path/to/config.py") doesn't work.

Import hooks I looked into and are a possibility, but these also don't quite give the semantics I wanted. Here's a minimal example of how it might work

import sys
import imp
import os

path_to_config_file = "./testdir/config.py"

class Config:
    def __init__(self, path):
        print path
        self.path = path

    def _get_code(self, fullname):
        # path_to_config_file might have come in via our options, etc
        f = open(path_to_config_file)
        # read in the file and compile it
        c = ""
        for line in f.readlines():
            c = c + line
        code = compile(c, fullname, 'exec')
        # false means this is not a package, code is the compiled code
        return False, code

    def find_module(self, fullname):
        # sufficient to return ourselves
        print fullname
        return self

    def load_module(self, fullname):
        # get the code
        ispkg, code = self._get_code(fullname)

        # create a new module
        mod = imp.new_module(fullname)
        # add it to the modules list
        sys.modules[fullname] = mod
        # set the file
        mod.__file__ = "&lt;%s&gt;" % (path_to_config_file)
        # set the module loader
        mod.__loader__ = self

        # exec code
        exec code in mod.__dict__

        # return the module object
        return mod

sys.path_hooks.append(Config)

import aconfigfile

print aconfigfile

aconfigfile.hello()

The issue I see with this is that the import aconfigfile isn't really clearly showing what I want. I really want to be able to pass any arbitrary file name to be imported, e.g. something like import ./a/config/config.file. As far as I can see, import hooks are more designed to import files held in, say, a zip or pak archive.