# 包和模块
Python 所有模块均属于唯一的模块对象类型,无论由 Python、C 或其他语言实现。
# 包
为构建模块化的代码组织体系,Python 通过包实现层次化命名空间管理,形成结构化模块资源池。所有包都是模块,但并非所有模块都是包。或者换句话说,包只是一种特殊的模块。
可以把包看成是文件系统中的目录,并把模块看成是目录中的文件。包既可包含常规模块,又可嵌套包含子包,形成树状结构化的代码容器体系。
常规包 (opens new window)通常以一个包含 __init__.py 文件的目录形式实现,当一个常规包被导入时,这个 __init__.py 文件会隐式地被执行,它所定义的对象会被绑定到该包命名空间中的名称。
__init__.py 文件可以包含与任何其他模块中所包含的 Python 代码相似的代码,Python 将在模块被导入时为其添加额外的属性。
以下文件系统布局定义了一个最高层级的 parent 包和三个子包。
parent/
__init__.py
one/
__init__.py
two/
__init__.py
three/
__init__.py
导入 parent.one 将隐式地执行 parent/__init__.py 和 parent/one/__init__.py,后续导入 parent.two 或 parent.three 则将分别执行 parent/two/__init__.py 和 parent/three/__init__.py。
# 模块导入
一个模块内的 Python 代码通过导入操作就能够访问另一个模块内的代码。
发起调用导入机制 (opens new window)的方式:
import(opens new window) 语句importlib.import_module()(opens new window)__import__()(opens new window)
# import
import (opens new window) 语句结合了两个操作:
- 搜索指定名称的模块
- 将搜索结果绑定到当前作用域中的名称
import (opens new window) 语句的搜索操作被定义为对 __import__() (opens new window) 函数的调用并带有适当的参数,__import__() (opens new window) 的返回值会被用于执行 import 语句的名称绑定操作。
对 __import__() (opens new window) 的直接调用将仅执行模块搜索,如果找到,则执行模块创建操作。只有 import (opens new window) 语句会执行名称绑定操作。
如果标识符列表改为一个星号 *,则在模块中定义的全部公有名称都将按 import 语句所在的作用域被绑定到局部命名空间。
from module import *
- 公有名称:在模块中可以被外部直接访问和使用的名称(如函数、类、变量等)。
- 私有名称:通常以下划线
_开头,表示这些名称是模块的内部实现细节,不建议外部访问。
一个模块所定义的公有名称,是由在模块的命名空间中检测一个名为 __all__ 的变量来确定的;如果有定义,它必须是一个字符串列表,其中的项为该模块所定义或导入的名称。
当使用 from module import * 语句时,只有 __all__ 列表中的名称会被导入。
如果没有定义 __all__,Python 会默认将所有不以下划线 _ 开头的名称视为公有名称。
from . import views
__all__ = ["views"]
# _import_
__import__ (opens new window) 函数会由 import (opens new window) 语句发起调用。不建议直接使用 __import__() (opens new window) 而应该用 importlib.import_module() (opens new window)。
__import__(name, globals=None, locals=None, fromlist=(), level=0)
本函数会导入模块 name,fromlist 给出了应从 name 模块中导入的对象或子模块的名称。level 指定是使用绝对还是相对导入,0 意味着仅执行绝对导入。
当 name 变量的形式为 package.module 时,通常将会返回最高层级的包,而不是以 name 命名的模块。但是,当给出了非空的 fromlist 参数时,则将返回以 name 命名的模块。
# import time
time = __import__('time', globals(), locals(), [], 0)
# import lxml.html
lxml = __import__('lxml.html', globals(), locals(), [], 0) # 返回顶层模块
# from lxml.html import fromstring, document_fromstring as doc_fromstring
_temp = __import__('lxml.html', globals(), locals(), ['fromstring', 'document_fromstring'], 0) # 返回 name 模块
fromstring = _temp.fromstring
doc_fromstring = _temp.document_fromstring
# importlib
importlib (opens new window) 包的主要目的是在 Python 源代码中提供 import (opens new window) 语句的实现。
importlib.import_module (opens new window)(name, package=None)
导入一个模块。参数
name指定了以绝对或相对导入方式导入什么模块。如果参数name使用相对导入的方式来指定,那么package参数必须设置为模块包名。