3

My question is similar to this one, though I'd like to go on step further.

I'm parsing a configuration file which calls a number of actions (with parameters) by name. For example:

"on_click": "action1", "args": {"rate": 1.5} 

Actions are python classes, inheriting from a base Action class, and can take named arguments. They're stored in an 'actions' subdirectory of the project, prefixed by an a_. I'd like to be able to add new actions by simply dropping a new file there, without having to change any other files. The project structure is like this:

myapp/
    actions/
        __init__.py
        baseaction.py
        a_pretty.py
        a_ugly.py
        ...
    run.py

All action classes provide a PerformAction() method and a GetName() method, which is what the configuration file refers to. In this example, a_pretty.py defines a class called PrettyPrinter. Calling GetName() on PrettyPrinter returns "action1".

I'd like to add the PrettyPrinter class to a dictionary with "action1" as the key, so I can instantiate new instances of it like the following:

args = {'rate': the_rate}
instantiated_action = actions['action1'](**args)
instantiated_action.PerformAction()

Currently, I have the following:

actions = [os.path.splitext(f)[0] for f in os.listdir("actions")
           if f.startswith("a_") and f.endswith(".py")]

for a in actions:

    try:
        module = __import__("actions.%s" % a, globals(), locals(), fromlist=["*"])
        # What goes here?
    except ImportError:
        pass

This is importing the action file, and if I print dir(module) I see the class names; I just don't know what I should be doing next (or if this whole approach is the correct way to go...).

Community
  • 1
  • 1
Rezzie
  • 4,763
  • 6
  • 26
  • 33

1 Answers1

2

If everything in your module are classes that you should instanciate, try something like this :

for a in actions:

try:
    module = __import__("actions.%s" % a, globals(), locals(), fromlist=["*"])
    # What goes here?
    # let's try to grab and instanciate objects
    for item_name in dir(module):
        try:
           new_action = getattr(module, item_name)()
           # here we have a new_action that is the instanciated class, do what you want with ;)
        except:
           pass

except ImportError:
    pass
Cédric Julien
  • 78,516
  • 15
  • 127
  • 132