【问题标题】:how to import a submodule in Python (without `exec`)如何在 Python 中导入子模块(没有 `exec`)
【发布时间】:2013-09-27 06:30:02
【问题描述】:

我想在不知道它的名字的情况下导入一个子模块,

>>> __import__("os.path")
<module 'os' from '/usr/lib/python3.3/os.py'>

不像你想象的那样工作,返回os,而不是os.path

我想出了这个解决方案。

def import_submodule(mod, submod):
    ns = {}
    exec_str = "from %s import %s as submod" % (mod, submod)
    exec(exec_str, ns, ns)
    return ns["submod"]

这给出了结果:

>>> import_submodule("os", "path")
<module 'posixpath' from '/usr/lib/python3.3/posixpath.py'>

但是我宁愿不使用 exec(),因为它的做法很糟糕,而且当 Python 的导入机制已经通过 __import__impimportlib 模块可用时,它似乎没有必要。

Python3.x 中有没有办法通过函数调用而不是使用exec() 来进行这种导入?

【问题讨论】:

  • 注意name.split('.'),然后循环使用getattr()来检索“子对象”; .path 在你的情况下。
  • 将您的示例基于os.path 可能会让您大吃一惊,因为it doesn't necessarily work like other modules
  • @ideasman42: __import__('parentmodule.submodule') 确实 导入submodule 但返回parentmodule
  • @MartijnPieters 我认为这不应该被视为重复,因为 OP 明确针对 python3.3 存在更好的答案(即importlib),答案中没有引用另一个问题。将此标记为重复可能意味着人们仍将使用其他自制解决方案而不是新的进口机器。在当前版本的 python 中,您几乎不需要直接调用 __import__

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


【解决方案1】:

使用importlib.import_module:

>>> import importlib
>>> importlib.import_module('os.path')
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>

这应该适用于 python2.7+ 和 3.1+。

【讨论】:

    【解决方案2】:

    请注意,如果您想:from A import B as C 作为函数调用,importlib.import_module 并不总是有效,因为 B 可能不是模块。

    这是一个使用 importlib 和 getattr 的函数。

    def my_import_from(mod_name, var_name):
        import importlib
        mod = importlib.import_module(mod_name)
        var = getattr(mod, var_name)
        return var
    

    所以这个:

    from os.path import dirname as var
    

    可以用这个代替:

    var = my_import_from("os.path", "dirname")
    

    这避免了 exec 并允许子模块和模块中定义的任何变量。

    由于我的问题明确表示要导入子模块,@Bakuriu 的答案是正确的,但是为了完整性而包括在内,它可能会帮助遇到同样问题的其他人。

    【讨论】:

      猜你喜欢
      • 2014-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      • 1970-01-01
      • 2022-07-26
      • 1970-01-01
      相关资源
      最近更新 更多