Python code in one module gains access to the code in another module by the process of importing it. The import statement is the most common way of invoking the import machinery, but it is not the only way. Functions such asimportlib.import_module() and built-in __import__() can also be used to invoke the import machinery.
The import statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope. The search operation of the import statement is defined as a call to the__import__() function, with the appropriate arguments. The return value of __import__() is used to perform the name binding operation of the import statement. See the import statement for the exact details of that name binding operation.
A direct call to __import__() performs only the module search and, if found, the module creation operation. While certain side-effects may occur, such as the importing of parent packages, and the updating of various caches (including sys.modules), only the import statement performs a name binding operation.
When calling __import__() as part of an import statement, the import system first checks the module global namespace for a function by that name. If it is not found, then the standard builtin __import__() is called. Other mechanisms for invoking the import system (such as importlib.import_module()) do not perform this check and will always use the standard import system.
When a module is first imported, Python searches for the module and if found, it creates a module object , initializing it. If the named module cannot be found, an ImportError is raised. Python implements various strategies to search for the named module when the import machinery is invoked. These strategies can be modified and extended by using various hooks described in the sections below.
Changed in version 3.3: The import system has been updated to fully implement the second phase of PEP 302. There is no longer any implicit import machinery - the full import system is exposed through sys.meta_path. In addition, native namespace package support has been implemented (see PEP 420).
importlib 模块提供了丰富的API和导入系统进行交互。例如importlib.import_module() 提供了一个比内建模块__import__() 更加推荐，更容易的API调用导入系统。可以查看importlib 模块的文档获取更多细节。
Python 只有一种模块对象，所有的模块都是这种类型，不管这个模块是否是用Python，C，或者其他语言实现。为了组织模块和提供命名层次, Python 引入 packages的概念。
重要的是请注意所有的包都是模块，但不是所有的模块都是包。换句话说，包只是一种特殊形式的模块。具体地说，任何包含__path__ 属性的模块 都被看作是一个包。
所有的模块都有名字。子模块的名字是通过点号从父模块中分离出来的，和Python标准的属性访问语法相似。因此，你可能有一个模块叫做 sys 和一个模块叫做 email, 它们拥有 email.mime 和 email.mime.text的子模块。
Python defines two types of packages, regular packages and namespace packages. Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an __init__.py file. When a regular package is imported, this __init__.py file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The __init__.py file can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.
For example, the following file system layout defines a top level parent package with three subpackages:
parent/ __init__.py one/ __init__.py two/ __init__.py three/ __init__.py
Importing parent.one will implicitly execute parent/__init__.py and parent/one/__init__.py. Subsequent imports of parent.two or parent.three will execute parent/two/__init__.py and parent/three/__init__.py respectively.
A namespace package is a composite of various portions, where each portion contributes a subpackage to the parent package. Portions may reside in different locations on the file system. Portions may also be found in zip files, on the network, or anywhere else that Python searches during import. Namespace packages may or may not correspond directly to objects on the file system; they may be virtual modules that have no concrete representation.
Namespace packages do not use an ordinary list for their __path__ attribute. They instead use a custom iterable type which will automatically perform a new search for