2014-01-23 49 views
3

我注意到其中类似下面的测试失败一些奇怪的情况:python是否会多次加载模块?

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 

(像这样的代码出现的泡菜模块)

我不认为我有任何进口钩,重装电话,或sys.modules操作会混淆python的正常导入缓存行为。

是否有任何其他原因为什么一个模块会被加载两次?我见过有关这方面的声明(例如https://stackoverflow.com/a/10989692/1332492),但我无法通过简单的独立脚本重现它。

+0

'assert x_ref == x'说什么? –

+0

也是假的,但我认为其实*调用*函数总是给出相同的结果 – ChrisB

+0

这些模块是否具有'__file__'属性?测试它们以查看它是否完全相同的模块。 –

回答

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'> 

从文档:

当名称变量的形式为package.module,通常情况下, 顶层包(名字直到第一个点)返回,而不是 按名称命名的模块。但是,如果给出非空的fromlist 参数,则会返回按名称命名的模块。

正如你可以看到__import__返回子模块,但只有顶部包。如果您还在包级别定义了function,那么将确实对有不同的参考。

如果你想加载一个模块,你应该使用importlib.import_module而不是__import__


至于回答您的实际问题:据我所知是没有办法导入同一模块,具有相同名称,不与进口机制乱搞的两倍。但是,你可以有一个包的子模块,这也是在sys.path可用,在您可以进口两次使用不同的名称这种情况下:

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

有时,这可能会导致问题,例如, pickle。如果您腌制submodule引用的内容,则不能使用submodule2作为参考将其取消。

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

+0

感谢您的额外信息。我对这个特定的失败仍然有些迷惑,但我怀疑它与你发布的最后一段代码有关 – ChrisB