【问题标题】:Does python ever multiply-load a module?python是否曾经多次加载模块?
【发布时间】:2014-01-24 02:27:45
【问题描述】:

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

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模块中)

我认为我没有任何会干扰 python 正常导入缓存行为的导入钩子、重新加载调用或 sys.modules 操作。

模块会被加载两次还有其他原因吗?我已经看到有关此的声明(例如,https://stackoverflow.com/a/10989692/1332492),但我无法在一个简单、孤立的脚本中重现它。

【问题讨论】:

  • assert x_ref == x 说什么?
  • 也是错误的,但我认为实际上调用函数总是给出相同的结果
  • 这些模块有__file__ 属性吗?测试它们是否是完全相同的模块。
  • 我不确定如何测试它,因为x.__module__ 给出的是字符串而不是模块对象。我可以打印__import__(x.__module__).__file__,但我不知道拿什么来比较
  • 我以为我在过去看到过一些奇怪的案例,进口方式不同......即用户会执行import x.y,然后是x.y.something(),然后另一个函数会执行from x import y,然后是y.something_else(),第二个函数看不到第一个函数的结果。但我现在无法重现它......

标签: python python-import


【解决方案1】:

我相信你误解了__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'>

来自文档:

当名称变量的格式为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__ 属性导入应该返回正确的模块。

【讨论】:

  • 感谢您提供额外信息。我仍然对特定的失败有点迷惑,但我怀疑它与您发布的最后一个代码 sn-p 有关
猜你喜欢
  • 2018-08-15
  • 2015-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多