Import in Python combines two operations :
- find (load and initialize) module
- enter new names in the current environment (as assignment operation
= )
At the search stage (item No. 1) —from the specification of the import structure :
This can be a submodule, eg foo.bar.baz . In this case, Python first tries to import foo , then foo.bar , and finally foo.bar.baz . ImportError is raised.
that is, import abc imports modules a , ab , abc and a more nested module cannot be imported successfully if the import is unsuccessful for any module above.
At the stage of naming (item number 2) :
If the module is not used for a module. The imported module must be accessed using its full name.
import abc in Python makes a name available in the current namespace (for example, in the global module namespace, which imports abc ) and assigns the attribute: ab and the attribute attribute: abc corresponding loaded modules (analog: a = sys.modules['a'] ; ab = sys.modules['a.b'] ; ..).
Although the question is with the podkha, because os not a Python package ( __path__ attribute is not set ) and os.path is a regular attribute (the same as os.walk ) with the difference that os.path is a module and os.py contains a hack : sys.modules['os.path'] = path (which allows the import os.path construction). import os itself already makes os.path available without import os.path .
To paraphrase a question using a more regular example:
Why when I do: import os.path import html.parser then os.walk html.escape is available to html.escape , which is in os html , although I obviously don’t import os html ?
import html.parser imports both html and (of course) html.parser modules, and since html/__init__.py (performed during the html import phase) defines the escape function, html.escape() also available as if we just executed import html .
For some reason, with your package, such a trick does not roll. What makes this happen?
If module.name doesn’t work after import module , it means that your module/__init__.py does not determine the name .
module.name : the module.name performance module.name not depend on __all__ . __all__ documents which names are public (formally names available from module import * ), so as not to add to each name that is not part of the interface, _ at the beginning (names like _name are excluded from the default from module import * ). But this does not prohibit an explicit call such as module._name (this should be avoided, but if you really want, then you can). Aside: do not use from module import * outside the REPL or outside the __init__.py file (an example of justified use: asyncio/__init__.py - asyncio provides a "flat" public interface (names are available directly as asyncio.name ), despite the fact that implementation is distributed across multiple nested modules).