7.11. import 语句

  1. import_stmt ::= "import" module ["as" identifier] ("," module ["as" identifier])*
  2. | "from" relative_module "import" identifier ["as" identifier]
  3. ("," identifier ["as" identifier])*
  4. | "from" relative_module "import" "(" identifier ["as" identifier]
  5. ("," identifier ["as" identifier])* [","] ")"
  6. | "from" module "import" "*"
  7. module ::= (identifier ".")* identifier
  8. relative_module ::= "."* module | "."+

基本的 import 语句(不带 from 子句)会分两步执行:

  • 查找一个模块,如果有必要还会加载并初始化模块。

  • 在局部命名空间中为 import 语句发生位置所处的作用域定义一个或多个名称。

当语句包含多个子句(由逗号分隔)时这两个步骤将对每个子句分别执行,如同这些子句被分成独立的 import 语句一样。

第一个步骤即查找和加载模块的详情 导入系统 一节中有更详细的描述,其中也描述了可被导入的多种类型的包和模块,以及可用于定制导入系统的所有钩子对象。 请注意这一步如果失败,则可能说明模块无法找到,或者 是在初始化模块,包括执行模块代码期间发生了错误。

如果成功获取到请求的模块,则可以通过以下三种方式一之在局部命名空间中使用它:

  • 如果模块名称之后带有 as,则跟在 as 之后的名称将直接绑定到所导入的模块。

  • 如果没有指定其他名称,且被导入的模块为最高层级模块,则模块的名称将被绑定到局部命名空间作为对所导入模块的引用。

  • 如果被导入的模块 不是 最高层级模块,则包含该模块的最高层级包的名称将被绑定到局部命名空间作为对该最高层级包的引用。 所导入的模块必须使用其完整限定名称来访问而不能直接访问。

from 形式使用的过程略微繁复一些:

  • 查找 from 子句中指定的模块,如有必要还会加载并初始化模块;

  • 对于 import 子句中指定的每个标识符:

    • 检查被导入模块是否有该名称的属性

    • 如果没有,尝试导入具有该名称的子模块,然后再次检查被导入模块是否有该属性

    • 如果未找到该属性,则引发 ImportError

    • 否则的话,将对该值的引用存入局部命名空间,如果有 as 子句则使用其指定的名称,否则使用该属性的名称

示例:

  1. import foo # foo imported and bound locally
  2. import foo.bar.baz # foo.bar.baz imported, foo bound locally
  3. import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb
  4. from foo.bar import baz # foo.bar.baz imported and bound as baz
  5. from foo import attr # foo imported and foo.attr bound as attr

如果标识符列表改为一个星号 ('*'),则在模块中定义的全部公有名称都将按 import 语句所在的作用域被绑定到局部命名空间。

一个模块所定义的 公有名称 是由在模块的命名空间中检测一个名为 all 的变量来确定的;如果有定义,它必须是一个字符串列表,其中的项为该模块所定义或导入的名称。 在 all 中所给出的名称都会被视为公有并且应当存在。 如果 all 没有被定义,则公有名称的集合将包含在模块的命名空间中找到的所有不以下划线字符 ('') 打头的名称。 _all 应当包括整个公有 API。 它的目标是避免意外地导出不属于 API 的一部分的项(例如在模块内部被导入和使用的库模块)。

通配符形式的导入 —- from module import * —- 仅在模块层级上被允许。 尝试在类或函数定义中使用它将引发 SyntaxError

当指定要导入哪个模块时,你不必指定模块的绝对名称。 当一个模块或包被包含在另一个包之中时,可以在同一个最高层级包中进行相对导入,而不必提及包名称。 通过在 from 之后指定的模块或包中使用前缀点号,你可以在不指定确切名称的情况下指明在当前包层级结构中要上溯多少级。 一个前缀点号表示是执行导入的模块所在的当前包,两个点号表示上溯一个包层级。 三个点号表示上溯两级,依此类推。 因此如果你执行 from . import mod 时所处位置为 pkg 包内的一个模块,则最终你将导入 pkg.mod。 如果你执行 from ..subpkg2 import mod 时所处位置为 pkg.subpkg1 则你将导入 pkg.subpkg2.mod。 有关相对导入的规范说明包含在 包相对导入 一节中。

importlib.import_module() 被提供用来为动态地确定要导入模块的应用提供支持。

7.11.1. future 语句

future 语句 是一种针对编译器的指令,指明某个特定模块应当使用在特定的未来某个 Python 发行版中成为标准特性的语法或语义。

future 语句的目的是使得向在语言中引入了不兼容改变的 Python 未来版本的迁移更为容易。 它允许基于每个模块在某种新特性成为标准之前的发行版中使用该特性。

  1. future_stmt ::= "from" "__future__" "import" feature ["as" identifier]
  2. ("," feature ["as" identifier])*
  3. | "from" "__future__" "import" "(" feature ["as" identifier]
  4. ("," feature ["as" identifier])* [","] ")"
  5. feature ::= identifier

future 语句必须在靠近模块开头的位置出现。 可以出现在 future 语句之前行只有:

  • 模块的文档字符串(如果存在),

  • 注释,

  • 空行,以及

  • 其他 future 语句。

在 Python 3.7 中唯一需要使用 future 语句的特性是 标注

future 语句所启用的所有历史特性仍然为 Python 3 所认可。 其中包括 absolute_import, division, generators, generator_stop, unicode_literals, print_function, nested_scopeswith_statement。 它们都已成为冗余项,因为它们总是为已启用状态,保留它们只是为了向后兼容。

future 语句在编译时会被识别并做特殊对待:对核心构造语义的改变常常是通过生成不同的代码来实现。 新的特性甚至可能会引入新的不兼容语法(例如新的保留字),在这种情况下编译器可能需要以不同的方式来解析模块。 这样的决定不能推迟到运行时方才作出。

对于任何给定的发布版本,编译器要知道哪些特性名称已被定义,如果某个 future 语句包含未知的特性则会引发编译时错误。

直接运行时的语义与任何 import 语句相同:存在一个后文将详细说明的标准模块 future,它会在执行 future 语句时以通常的方式被导入。

相应的运行时语义取决于 future 语句所启用的指定特性。

请注意以下语句没有任何特别之处:

  1. import __future__ [as name]

这并非 future 语句;它只是一条没有特殊语义或语法限制的普通 import 语句。

在默认情况下,通过对Code compiled by calls to the 内置函数 exec()compile() 的调用所编译的代码如果出现于一个包含有 future 语句的模块 M 之中,就会使用 future 语句所关联的语法和语义。 此行为可以通过 compile() 的可选参数加以控制 —- 请参阅该函数的文档以了解详情。

在交互式解释器提示符中键入的 future 语句将在解释器会话此后的交互中有效。 如果一个解释器的启动使用了 -i 选项启动,并传入了一个脚本名称来执行,且该脚本包含 future 语句,它将在交互式会话开始执行脚本之后保持有效。

参见

  • PEP 236 - 回到 future
  • 有关 future 机制的最初提议。