用于导入模块的顺序 Python 是什么?

What's the order Python used to import module?

我在 python import 语句中遇到了一些奇怪的事情。

假设我的文件结构如下:

foo\
    __init__.py
    bar.py
    os.py

bar.py中的代码(其他文件为空)

import os
print os.__file__

奇怪的是当我 运行 python -m foo.bar, 它打印

foo/os.pyc

但是,当我将 direcotry 更改为 foo 和 运行 python -m bar 时,它会打印

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc

我运行脚本的两种方式有什么区别?

一句话,导入模块的顺序Python是什么?

从官方文档中,我找到了好几篇关于这个问题的文字(它们让我更加困惑)

  1. 6.1.2. The Module Search Path

the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path.

  1. sys.path

the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first.

  1. 6.4.2. Intra-package References

In fact, such references are so common that the import statement first looks in the containing package before looking in the standard module search path.

...

If the imported module is not found in the current package (the package of which the current module is a submodule), the import statement looks for a top-level module with the given name.

What's the difference between the two ways I run script?

区别在于 foo 是否(从 python 的角度来看)是一个已加载的模块。

如果你 运行 python -m foo.barfoo 是一个有效的模块。即使使用 Python 2.7,import os 仍然是 relative import,因此 os 会针对包含模块(即 foo)进行解析,首先:

https://docs.python.org/2/tutorial/modules.html#intra-package-references:

The submodules often need to refer to each other. For example, the surround module might use the echo module. In fact, such references are so common that the import statement first looks in the containing package before looking in the standard module search path.

当你 运行 python -m bar 时,bar 是顶级模块,即它没有包含模块。在那种情况下 import os 会通过 sys.path

import bla 的默认模块搜索是

  1. 如果包含模块存在,则对包含模块进行相对导入。
  2. 进入 sys.path 并使用第一个成功的导入。

要禁用 (1),您可以

from __future__ import absolute_import  

在模块的最顶部。

令人困惑?绝对。