Dynamic module import of class list from module given its full path

1k views Asked by At

First, it seems proper to me to state that I've read over the following questions:

And, I don't feel like they address my use case. That said, here's my question:

How can I dynamically import from a configuration file like this:

[imports]
/var/imports/foo.py = baz monkey
/var/imports/bar.py = ape

So that I can call the known objects via RESTful interface like this.

# http://localhost/data?operation=get&class=baz&id=1
def handler(object):
  def handle(self):
    cls = instantiate(request.args["class"])
    meth = request.args["operation"]
    return getattr(cls,meth,request.args)

And it could respond with the result of get() on an instance of that class.

2

There are 2 answers

0
Ned Batchelder On BEST ANSWER

Here's a rough sketch of a class registry you could use like this:

class ClassRegistry(object):

    def __init__(self):
        self.classes = {}

    def add_file_classes(self, fname, class_list):
        globals = {}
        exec open(fname) in globals
        for class_name in class_list:
            self.classes[class_name] = getattr(globals, class_name)

    def get_class(self, class_name):
        return self.classes[class_name]

Read your config file and invoke add_file_classes like this:

reg = ClassRegistry()
reg.add_file_classes("/var/imports/foo.py", ["baz", "monkey"])
reg.add_file_classes("/var/imports/bar.py", ["ape"])

then later:

cls = reg.get_class("baz")

Note that we aren't actually importing the files, simply executing them and collecting their results.

0
Jochen Ritzel On

Look at the 2nd link again. It already mentions imp.load_source:

import imp

# some sort of shared dict for everything imported
loaded = {}

def load(path, from_list):
    # load the path
    module = imp.load_source( "dummy", path)
    for name in from_list:
        # add the names
        loaded[name] = getattr(module, name)

#lets say you have this:
data = "/var/imports/foo.py", ["baz"]
load(*data)
print loaded['baz'] # whatever foo.baz was

Now you can do something like this:

def instantiate( clsname ):
    obj = loaded[clsname]
    return obj()

I hope this gets you started.