简体   繁体   English

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

[英]What's the order Python used to import module?

I encounted something strange about python import statement. 我遇到了一些关于python import语句的奇怪现象。

Let's say that I have a file structure like below: 假设我的文件结构如下:

foo\
    __init__.py
    bar.py
    os.py

Codes in bar.py (Other files are empty) bar.py中的代码(其他文件为空)

import os
print os.__file__

The strange thing is when I run python -m foo.bar , it prints 奇怪的是,当我运行python -m foo.bar ,它会打印

foo/os.pyc

However, when I changed direcotry to foo , and run python -m bar , it prints 但是,当我将direcotry更改为foo并运行python -m bar ,它会打印

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

What's the difference between the two ways I run script? 我运行脚本的两种方式有什么区别?

In a word, what's the order Python used to import module? 总之, Python用于导入模块的顺序是什么?

From official documents, I found several text about this problem (They made me even more confused) 从官方文件中,我发现了一些有关此问题的文字(它们使我更加困惑)

  1. 6.1.2. 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 . 如果找不到,它将在变量sys.path给出的目录列表中搜索名为spam.py的文件。

  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. 该列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录。 If the script directory is not available (eg 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. 如果脚本目录不可用(例如,如果交互式调用解释器或从标准输入中读取脚本),则path [0]为空字符串,该字符串将引导Python首先搜索当前目录中的模块。

  1. 6.4.2. 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. 实际上,这样的引用非常普遍,以至于import语句首先查看包含的包,然后再查看标准模块的搜索路径。

... ...

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. 如果在当前程序包(当前程序包是其子模块的程序包)中未找到导入的模块,则import语句将查找具有给定名称的顶级模块

What's the difference between the two ways I run script? 我运行脚本的两种方式有什么区别?

The difference is if foo is (from python's view) a loaded module or not. 区别在于foo是否(从python的角度来看)是已加载的模块。

If you run python -m foo.bar , foo is a valid module. 如果运行python -m foo.bar ,则foo是有效的模块。 Even with Python 2.7, import os is still a relative import and hence os gets resolved against the containing module (ie foo ), first: 即使使用Python 2.7, import os仍然是相对导入 ,因此os针对包含的模块(即foo )进行解析:

https://docs.python.org/2/tutorial/modules.html#intra-package-references : 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. 实际上,这样的引用非常普遍,以至于import语句首先查看包含的包,然后再查看标准模块的搜索路径。

When you run python -m bar , bar is a top level module, ie it has no containing module. 当您运行python -m barbar是一个顶级模块,即它没有包含模块。 In that case import os goes to through sys.path . 在这种情况下, import os通过sys.path进入。

The default module search for an import bla is import bla的默认模块搜索为

  1. If a containing module exists, do a relative import against the containing module. 如果存在包含模块,请对该包含模块进行相对导入。
  2. Go into sys.path and use the first successful import. 进入sys.path并使用首次成功导入。

To disable (1), you can 要禁用(1),您可以

from __future__ import absolute_import  

at the very top of a module. 在模块的最上方。

Confusing? 令人困惑? Absolutely. 绝对。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM