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

Yon*_*Yon 11 python import module python-2.7

我对python import语句有些奇怪.

假设我有一个如下所示的文件结构:

foo\
    __init__.py
    bar.py
    os.py
Run Code Online (Sandbox Code Playgroud)

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

import os
print os.__file__
Run Code Online (Sandbox Code Playgroud)

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

foo/os.pyc
Run Code Online (Sandbox Code Playgroud)

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

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc
Run Code Online (Sandbox Code Playgroud)

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

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

从官方文件中,我发现了几个关于这个问题的文字(他们让我更加困惑)

  1. 6.1.2.模块搜索路径

解释器首先搜索具有该名称的内置模块.如果未找到,则会在变量sys.path给出的目录列表中搜索名为spam.py的文件.

  1. sys.path中

此列表的第一项path [0]是包含用于调用Python解释器的脚本的目录.如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本),path [0]是空字符串,它指示Python首先搜索当前目录中的模块.

  1. 6.4.2.封装内参考

事实上,这样的引用是如此常见,以至于在查看标准模块搜索路径之前,import语句首先在包含包中查找.

...

如果在当前包(当前模块是子模块的包)中找不到导入的模块,则import语句将查找具有给定名称的顶级模块.

dhk*_*hke 5

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

区别在于foo(从python的视图)是否是一个加载的模块.

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

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

子模块通常需要相互引用.例如,环绕声模块可能使用echo模块.事实上,这样的引用是如此常见,以至于在查看标准模块搜索路径之前,import语句首先在包含包中查找.

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

默认模块搜索import bla

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

要禁用(1),您可以

from __future__ import absolute_import  
Run Code Online (Sandbox Code Playgroud)

在模块的最顶层.

混乱?绝对.

  • [包含]>内置模块> sys.path (3认同)