从虚线字符串

时间:2016-12-15 00:25:18

标签: python python-2.7 python-3.x

关于如何从一个虚线字符串(例如lookup('my.module.some_function'))中查找python中的函数或类,有很多答案,但据我所知,它们都假设字符串的第一部分是一个模块,最后一部分是模块级别的东西。

我特别想找到一个可以处理静态类方法(例如下面的例子)和模块级函数的解决方案,但似乎应该有一个python内置函数或一个使用内置函数的简单函数可以处理所有情况(奖励积分)对于嵌套类!)。

适用于所有常见版本的答案将是理想的。如果它不可能一般地处理这个问题,我认为一个证明加载函数与静态方法的机制的答案就足够了,未来的问题读者可以使用它作为如何推出自己的解决方案来处理他们需要的案例。

例如,给出以下定义:

# In /my/module.py

def my_func():
    pass

class MyClass(object):
    def __init__():
        pass

    @staticmethod  # or @classmethod
    def factory():
        return MyClass()

我正在使用支持以下内容的查找功能:

f = lookup('my.module.my_func')
f()  # Equivalent to calling my_func()

f = lookup('my.module.MyClass')
f()  # Equivalent to calling MyClass()

f = lookup('my.module.MyClass.factory')
f()  # Equivalent to calling MyClass.factory()

1 个答案:

答案 0 :(得分:0)

它一点也不漂亮,但这里有你可以使用的东西:

from importlib import import_module

def lookup(st):
    # first we have to find the maximal module path
    # in the provided string, so we work right to
    # left across the dot pieces.
    pieces = st.split('.')
    n = len(pieces)
    module = None
    while n > 0:
        n -= 1
        rg = pieces[:n]
        # if we haven't been able to resolve a module, break out of the loop
        if not rg: break
        module_name = '.'.join(rg)
        try:
            # once we find a matching module, break out of this loop
            module = import_module(module_name)
            break
        except ImportError:
            pass
    if not module:
        raise ImportError('No module specified in %s' % st)
    # once we have the specified module, we can just repeatedly
    # call getattr to find the specified function or class.  This 
    # should work for classes, first-class functions, and class 
    # functions.  I am not sure about static class functions.
    result = module
    for x in pieces[n:]:
        result = getattr(result, x, None)
        if not result:
            raise AttributeError('could not resolve %s' % x)
    return result