hello fellows,

I seem to have a little problem:

I tried to use the function getattr(object, attribute) with two strings which is being read from a xml file as arguments, and seem to have a problem with sending the first one as a string. the function thinks that the string object itself is the object argument, when what i meant was that the VALUE of my string will be sent to the function as a name of a module in my program.

the second argument however, isn't doing any problems, and is being treated as the object of the value of the string, and not as a string object itself.
weird!

maybe a conversion between a string object and a module object is possible? i don't know...

help?

Dani AI

Generated

Short clarification and a safer pattern for dynamic lookups from XML.

The core issue that ran into is that getattr() expects an actual Python object as its first argument and a string attribute name as its second. If both values from XML are plain strings, passing the module name string directly to getattr() makes Python try to get the attribute from the string object itself. ’s exec() trick and ’s note about importing are on the right track; the modern, safer way is to turn the module-name string into a real module object and then resolve attributes.

A compact, robust resolver handles dotted names (e.g. "package.module.Class.method") by finding the longest importable module prefix, importing it with importlib.import_module, then walking the remaining attribute names with getattr():

import importlib

def resolve_dotted(path):
    parts = path.split('.')
    for i in range(len(parts), 0, -1):
        mod_name = '.'.join(parts[:i])
        try:
            mod = importlib.import_module(mod_name)
            obj = mod
            for a in parts[i:]:
                obj = getattr(obj, a)
            return obj
        except ImportError:
            continue
    raise ImportError("No importable module found in %r" % path)

Practical tips: strip whitespace from XML values and normalize encodings; catch and log ImportError/AttributeError with the offending name; verify callable(obj) if the intent is to call the result. Avoid exec() on untrusted input. For security and maintainability prefer a whitelist or a registry (a dictionary mapping allowed XML keys to actual callables) instead of importing arbitrary names from user-provided XML. This approach complements ’s and ’s suggestions while using a clearer, safer API and handling nested attributes and common error cases.

Recommended Answers

All 5 Replies

Would be nice to have an actual example!

Check the "mimic a C struct type with an empty Python class " in the Starting Python sticky. You could do something along that line.

Hmm. Here's one way around it, using exec() instead of getattr():

import sys
# For our example, let's use random.sample() as the desired attribute
# This function takes as input a list and an integer n and returns a
# random, non-redundant selection of n elements from the list
modname = "random"
attname = "sample"
# Import the module using exec, set the function to a wrapper variable
exec("import "+modname)
exec("sampleWrapper = "+modname+"."+attname)
# Test the wrapper variable
print sampleWrapper([1, 2, 3, 4, 5, 6], 2)

Something more in line with what you were thinking of might be:

exec("import "+modname)
exec("mod = "+modname)
# Now we can use mod as though it were the actual module
sampleWrapper = getattr(mod, "sample")
print sampleWrapper([1, 2, 3, 4, 5, 6], 2)

It's tricky, but it works!

Neat! Never thought of exec() that way!

Cool!
Thanks very much!

hello fellows,

I seem to have a little problem:

I tried to use the function getattr(object, attribute) with two strings which is being read from a xml file as arguments, and seem to have a problem with sending the first one as a string. the function thinks that the string object itself is the object argument, when what i meant was that the VALUE of my string will be sent to the function as a name of a module in my program.

the second argument however, isn't doing any problems, and is being treated as the object of the value of the string, and not as a string object itself.
weird!

maybe a conversion between a string object and a module object is possible? i don't know...

help?

Try

fn = getattr(__import__('example_module'), 'example_function')

The getattr builtin requires the module object, therefore you have to load that module using __import__() first.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.