【问题标题】:import vs __import__( ) vs importlib.import_module( )?导入 vs __import__() vs importlib.import_module()?
【发布时间】:2015-01-30 08:13:59
【问题描述】:

我注意到 Flask 正在使用 Werkzeug 来 __import__ 一个模块,我有点困惑。我去查看了上面的文档,发现它似乎以某种方式让您在查找模块的位置方面提供了更多控制权,但我不确定确切如何,而且我的想法为零它与importlib.import_module 有何不同。

Werkzeug 示例中的奇怪之处在于它只是说 __import__(import_name),所以我看不出这与仅使用 import 语句有什么不同,因为它忽略了可选的额外参数。

谁能解释一下?我查看了其他人之前就 SO 提出过类似问题,但他们的问题措辞不是很清楚,而且答案根本没有解决这个问题。

【问题讨论】:

  • 使用__import__,其中you want to import a module whose name is only known at runtime。除此之外......正如你所说,与导入相比,这给了你更多的力量
  • 如果没记错的话,有一段 David Beasely 正在导入的视频,在视频中他提到 WerkZeug 出于某种原因重载了导入。

标签: python python-import


【解决方案1】:

__import__ 是一个低级的钩子函数,用于导入模块;它可用于通过将模块名称作为变量导入来动态导入模块,这是import 语句不允许您这样做的。

importlib.import_module() 是该钩子的包装器* 为该功能生成一个不错的 API;它是 Python 2 的最新补充,在 Python 3 中更加充实。使用 __import__ 的代码库通常这样做是因为它们希望与较旧的 Python 2 版本保持兼容,例如Python 2.7 之前的任何东西。

使用__import__ 的一个副作用可能是它返回导入的模块并且不向命名空间添加任何内容;如果您不想要新名称,则可以使用它导入,而无需删除新名称; using import somename 会将 somename 添加到您的命名空间,但 __import__('somename') 会返回导入的模块,然后您可以忽略它。出于这个原因,Werkzeug 在一个地方使用了钩子。

所有其他用途都与动态导入有关。 Werkzeug 仍然支持 Python 2.6,所以不能使用 importlib


*importlib 是纯 Python 实现,import_module() 将使用该实现,而 __import__ 将使用 C 优化版本。两个版本都回调importlib._bootstrap._find_and_load(),所以区别主要是学术性的。

【讨论】:

  • 我不太明白您所说的“如果您不想要新名称,您可以使用它导入而无需删除新名称”。如果你有时间,你能不能把它充实起来,就像你在和一个蹒跚学步的孩子说话一样?
  • @Aerovistae:更新了一点; import sys 将名称 sys 添加到您的命名空间(绑定到模块),__import__('sys')sys 模块对象返回给调用者,然后调用者可以随意忽略该对象。
  • @MartijnPieters 你所说的命名空间是指sys.modules吗?
  • @NeoWang:命名空间是指模块的全局变量。这些作为字典存储在module 实例上,而后者又存储在sys.modules 中。
  • @Mahesha999:要从存储在字符串中的源代码动态生成模块,您根本不需要查看__import__。使用module = imporlib.util.module_from_spec(importlib.machinery.ModuleSpec(module_name, None, origin='<string>')) 创建一个空模块实例,使用sys.modules[module_name] = module 存储模块,然后使用exec(sourcecode, module.__dict__) 执行您的源代码。并且永远不要执行用户提供的代码,这是非常不安全的。
【解决方案2】:

__import__(import_name),所以我看不出这与 只使用 import 语句

__import__() 和 importlib.import_module() 都允许您在模块名称为字符串时导入模块。你不能写:

x = 're'
import x

否则你会得到:

 File "1.py", line 3, in <module>
 import x ImportError: No module named x

【讨论】:

    猜你喜欢
    • 2011-02-04
    • 2016-08-31
    • 2018-07-10
    • 1970-01-01
    • 2023-02-02
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    相关资源
    最近更新 更多