Search code examples
pythonpython-3.xgetattr

How to pass a string as an object to getattr python


I have a number of functions that need to get called from various imported files.

The functions are formated along the lines of this:

a.foo
b.foo2
a.bar.foo4
a.c.d.foo5

and they are passed in to my script as a raw string.

I'm looking for a clean way to run these, with arguments, and get the return values

Right now I have a messy system of splitting the strings then feeding them to the right getattr call but this feels kind of clumsy and is very un-scalable. Is there a way I can just pass the object portion of getattr as a string? Or some other way of doing this?

import a, b, a.bar, a.c.d

if "." in raw_script:
    split_script = raw_script.split(".")
    if 'a' in raw_script:
        if 'a.bar' in raw_script:
            out = getattr(a.bar, split_script[-1])(args)
        if 'a.c.d' in raw_script:
            out = getattr(a.c.d, split_script[-1])(args)
        else:
            out = getattr(a, split_script[-1])(args)
    elif 'b' in raw_script:
        out = getattr(b, split_script[-1])(args)

Solution

  • Try this:

    def lookup(path):
        obj = globals()
        for element in path.split('.'):
            try:
                obj = obj[element]
            except KeyError:
                obj = getattr(obj, element)
        return obj
    

    Note that this will handle a path starting with ANY global name, not just your a and b imported modules. If there are any possible concerns with untrusted input being provided to the function, you should start with a dict containing the allowed starting points, not the entire globals dict.