python是否会多次加载模块?

时间:2014-01-23 15:40:21

标签: python python-import

我注意到一些奇怪的情况,例如以下测试失败:

x = <a function from some module, passed around some big application for a while>

mod = __import__(x.__module__)
x_ref = getattr(mod, x.__name__)
assert x_ref is x  # Fails

(这样的代码出现在pickle模块中)

我认为我没有任何导入钩子,重载调用或sys.modules操作,这些操作会破坏python的正常导入缓存行为。

为什么模块会被加载两次还有其他原因吗?我已经看到了关于此的说法(例如,https://stackoverflow.com/a/10989692/1332492),但我无法用简单,孤立的脚本重现它。

1 个答案:

答案 0 :(得分:3)

我相信你误解了__import__的工作方式:

>>> from my_package import my_module
>>> my_module.function.__module__
'my_package.my_module'
>>> __import__(my_module.function.__module__)
<module 'my_package' from './my_package/__init__.py'>

来自文档:

  

当name变量的格式为package.module时,通常是   返回顶级包(直到第一个点的名称),而不是   按名称命名的模块。但是,当非空fromlist时   给出参数,返回名称命名的模块。

正如您所看到的,__import__ 会返回子模块,而只返回 top 包。如果您还在包级别定义了function,则 确实会对其进行不同的引用。

如果您只想加载模块,则应使用importlib.import_module代替__import__


至于回答你的实际问题:AFAIK没有办法导入同一个模块,同名,两次没有搞乱导入机制。但是,您可以拥有sys.path中也可用的包的子模块,在这种情况下,可以使用不同的名称 将其导入两次:

from some.package import submodule
import submodule as submodule2
print(submodule is submodule2)   # False. They have *no* relationships.

这有时会导致问题,例如pickle。如果您挑选submodule引用的内容,则无法使用submodule2作为参考来解开它。

但是这并没有解决您提供给我们的具体示例,因为使用__module__属性导入应返回正确的模块。