如何将字符串作为对象传递给getattr python

时间:2017-10-19 20:40:56

标签: python python-3.x getattr

我有许多需要从各种导入文件中调用的函数。

这些功能按照以下方式形成:

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

并将它们作为原始字符串传递给我的脚本。

我正在寻找一种干净的方式来运行这些,带参数,并获得返回值

现在我有一个混乱的系统,分裂字符串,然后将它们送到正确的getattr调用,但这感觉有点笨拙,非常不可扩展。有没有办法可以将getattr的对象部分作为字符串传递?或者其他一些方法呢?

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)

2 个答案:

答案 0 :(得分:1)

试试这个:

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

请注意,这将处理以任何全局名称开头的路径,而不仅仅是ab导入的模块。如果对函数提供不受信任的输入存在任何可能的问题,则应该从包含允许的起始点的dict开始,而不是整个全局变量dict。

答案 1 :(得分:1)

很难从你的问题中看出来,但听起来你有一个命令行工具,你运行my-tool <function> [options]。您可以像这样使用importlib,避免大多数getattr来电:

import importlib

def run_function(name, args):
    module, function = name.rsplit('.', 1)
    module = importlib.import_module(module)
    function = getattr(module, function)
    function(*args)

if __name__ == '__main__':
    # Elided: retrieve function name and args from command line
    run_function(name, args)