Question

I'm noticing some weird situations where tests like the following fail:

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

(Code like this appears in the pickle module)

I don't think I have any import hooks, reload calls, or sys.modules manipulation that would mess with python's normal import caching behavior.

Is there any other reason why a module would be loaded twice? I've seen claims about this (e.g, https://stackoverflow.com/a/10989692/1332492), but I haven't been able to reproduce it in a simple, isolated script.

Was it helpful?

Solution

I believe you misunderstood how __import__ works:

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

From the documentation:

When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name. However, when a non-empty fromlist argument is given, the module named by name is returned.

As you can see __import__ does not return the sub-module, but only the top package. If you have function also defined at package level you will indeed have different references to it.

If you want to just load a module you should use importlib.import_module instead of __import__.


As to answer you actual question: AFAIK there is no way to import the same module, with the same name, twice without messing around with the importing mechanism. However, you could have a submodule of a package that is also available in the sys.path, in this case you can import it twice using different names:

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

This sometimes can cause problems with, e.g., pickle. If you pickle something referenced by submodule you cannot unpickle it using submodule2 as reference.

However this doesn't address the specific example you gave us, because using the __module__ attribute the import should return the correct module.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top