【问题标题】:How can I import a python module function dynamically?如何动态导入 python 模块函数?
【发布时间】:2011-04-06 02:13:58
【问题描述】:

假设 my_function() 位于 my_apps.views 我想动态导入 my_function 而不使用 execeval 之类的东西。

有没有办法做到这一点。我想做类似的事情:

my_function = import_func("my_apps.views.my_function")

my_function()
   ... code is executed

【问题讨论】:

    标签: python function import module


    【解决方案1】:
    def import_by_string(full_name):
        module_name, unit_name = full_name.rsplit('.', 1)
        return getattr(__import__(module_name, fromlist=['']), unit_name)
    
    
    exists = import_by_string("os.path.exists")
    

    【讨论】:

    • 自 2.4 版(自 2004 年起)以来,Python 有了函数rsplit(),执行module_name, unit_name = full_name.rsplit('.', 1) 比您正在执行的操作要高效得多。
    • 谢谢。没想到。
    【解决方案2】:

    你想要的

    my_function = getattr(__import__('my_apps.views'), 'my_function')
    

    如果你在编译时碰巧知道函数的名字,你可以把它缩短为

    my_function = __import__('my_apps.views').my_function
    

    这将加载my_apps.views,然后将其my_function 属性分配给本地my_function

    如果您确定只需要 一个 功能,那么这是可以接受的。如果你想要多个属性,你可以这样做:

    views = __import__('my_apps.views')
    my_function = getattr(views, 'my_function')
    my_other_function = getattr(views, 'my_other_function')
    my_attribute = getattr(views, 'my_attribute')
    

    因为它更具可读性并且可以节省您对__import__ 的一些调用。再说一遍,如果你知道名字,代码可以像上面那样缩短。

    您也可以使用 imp 模块中的工具执行此操作,但它更复杂。

    【讨论】:

    • 上面的 import 语句会有问题(AttributeError)。除非指定了导入列表,否则导入会返回第一个模块 (my_apps)。你需要类似:my_function = __import__('my_apps.views', globals(), locals(), ['my_function']).my_functionpython doc about import
    • 对我来说,这会尝试从my_apps而不是my_apps.views导入函数。
    【解决方案3】:

    我刚刚写了这段代码,看起来很多人都需要,所以即使稍后我展示它

    def my_import(module_name,func_names = [],cache = False):
        if module_name in globals() and cache:
            return True
        try: 
            m = __import__(module_name, globals(), locals(), func_names, -1)
            if func_names:
                for func_name in func_names:
                    globals()[func_name] = getattr(m,func_name)
            else:
                globals()[module_name] = m
            return True
        except ImportError:
            return False
    def my_imports(modules):
        for module in modules:
            if type(module) is tuple:
                name = module[0]
                funcs = module[1]
            else:
                name = module
                funcs = []
            if not my_import(name, funcs):
                 return module
        return ''
    
    def checkPluginsImports(plugin,modules):
        c = my_imports(modules)
        if c:
            print plugin +" has errors!: module '"+c+"' not found"
    
    # example: file test.py with "x" function
    def d():
        checkPluginsImports('demoPlugin',[('test',['x'])])
    
    d()
    x()
    

    【讨论】:

      【解决方案4】:

      注意Python 2.7 添加了importlib module__import__() 的便捷包装器和 3.1 功能的反向移植。

      此模块是 Python 3.1 中功能更全面的同名包中可用功能的一个小子集,它提供了完整的导入实现。此处提供的内容有助于轻松从 2.7 过渡到 3.1。

      importlib.import_module(name, package=None)

      导入一个模块。 name 参数以绝对或相对术语(例如 pkg.mod 或 ..mod)指定要导入的模块。如果名称是用相对术语指定的,则必须将 package 参数指定给要充当解析包名称的锚的包(例如 import_module('..mod', 'pkg.subpkg') 将 import pkg .mod)。指定的模块会被插入到 sys.modules 中并返回。

      【讨论】:

      • Python 2.7 中可用的 importlib 子集也可在 PyPI 上使用,并在此处向后移植以与 Python 2.3 及更高版本一起使用。
      猜你喜欢
      • 2011-04-17
      • 2020-11-30
      • 2017-07-13
      • 1970-01-01
      • 1970-01-01
      • 2013-11-01
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多