urllib3 中的相对导入
Relative import in urllib3
我正在研究 python 如何加载模块。
我从 requests
开始加载 urllib3
。
我找到了 those line:
from .packages.six.moves.http_client import (
IncompleteRead as httplib_IncompleteRead
)
在名为 src/urllib3/exceptions.py
的文件中
那个导入是相对的,所以我正在寻找文件夹 src/urllib3/packages/six/moves/http_client.py
或 src/urllib3/packages/six/moves/http_client/__init__.py
这些文件不存在。
幸运的是 src/urllib3/packages/six.py
定义了一个新的模块加载器,所以导入 .packages.six.moves.http_client
需要 http_client
核心 python 模块。
但我不明白 src/urllib3/packages/six.py
是如何加载的。
我没有找到那种导入。
有没有办法知道哪个模块直接加载src/urllib3/packages/six.py
?
我已经按照建议 here 尝试使用 __name__
全局变量。它的值为 urllib3.packages.six
但 urllib3.packages
不会加载该文件。
from .packages.six.moves.http_client import ...
表达式导致 .packages.six
被加载 首先 。 Python 始终将嵌套包引用中的所有包加载到模块。
因此 .packages.six.moves.http_client
导致 Python 首先查找 urllib3.packages
,然后查找 urllib3.packages.six
,依此类推。导入机制通过在 sys.modules
中查找全名来实现,如果不存在,则触发模块搜索并为每个模块加载。
第一次发生这种情况,sys.modules['urllib3.packages.six']
还不存在,导入机器找到文件 urllib3/packages/six.py
,导入它,before 它'我会寻找更多的名字。
而且,正如您发现的那样,导入 six.py
模块文件的行为导致该模块添加 sys.modules['urllib3.packages.six.moves']
和对标准库模块的进一步引用。
Python 的进口机械相当复杂; Python 参考文档在 The import system 中全面介绍了这一点;要查找的具体条目是:
A direct call to __import__()
performs only the module search and, if found, the module creation operation. While certain side-effects may occur, such as the importing of parent packages, and the updating of various caches (including sys.modules), only the import statement performs a name binding operation.
以下
Importing parent.one
will implicitly execute parent/__init__.py
and parent/one/__init__.py.
Subsequent imports of parent.two
or parent.three
will execute parent/two/__init__.py
and parent/three/__init__.py
respectively.
及The module cache以下:
The first place checked during import search is sys.modules
. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So if foo.bar.baz
was previously imported, sys.modules
will contain entries for foo
, foo.bar
, and foo.bar.baz
. Each key will have as its value the corresponding module object.
(我添加的引用部分中的粗体强调)。
请注意 urllib3/packages
目录中的所有内容都是 vendorized 包;一个通常会独立安装的项目,但 urllib3
项目决定将其与自己的发行版打包在一起,以避免担心支持哪些版本。 six
就是这样一个独立的项目,可以安装from PyPI.
您可以在 six.moves
virtual package in the six
project documentation 上找到更多信息。它的目的是让库开发人员更容易编写与 Python 2 和 Python 3 兼容的代码,而不必担心在任一版本上导入什么标准库名称。
Python 中关于导入函数的一个值得注意的事情是,它不仅可以导入模块本身,还可以从其中导入变量、classes、函数(通常是名称空间)。
在示例中,您提供了:
from .packages.six.moves.http_client import (
IncompleteRead as httplib_IncompleteRead
)
import 语句引用 src/urllib3/packages/six.py
模块中的 moves 变量,该变量在该文件的第 316 行定义并分配给 class 的实例_MovedItems:
moves = _MovedItems(__name__ + ".moves")
和http_client是一个属性或这个class实例的方法
我正在研究 python 如何加载模块。
我从 requests
开始加载 urllib3
。
我找到了 those line:
from .packages.six.moves.http_client import (
IncompleteRead as httplib_IncompleteRead
)
在名为 src/urllib3/exceptions.py
那个导入是相对的,所以我正在寻找文件夹 src/urllib3/packages/six/moves/http_client.py
或 src/urllib3/packages/six/moves/http_client/__init__.py
这些文件不存在。
幸运的是 src/urllib3/packages/six.py
定义了一个新的模块加载器,所以导入 .packages.six.moves.http_client
需要 http_client
核心 python 模块。
但我不明白 src/urllib3/packages/six.py
是如何加载的。
我没有找到那种导入。
有没有办法知道哪个模块直接加载src/urllib3/packages/six.py
?
我已经按照建议 here 尝试使用 __name__
全局变量。它的值为 urllib3.packages.six
但 urllib3.packages
不会加载该文件。
from .packages.six.moves.http_client import ...
表达式导致 .packages.six
被加载 首先 。 Python 始终将嵌套包引用中的所有包加载到模块。
因此 .packages.six.moves.http_client
导致 Python 首先查找 urllib3.packages
,然后查找 urllib3.packages.six
,依此类推。导入机制通过在 sys.modules
中查找全名来实现,如果不存在,则触发模块搜索并为每个模块加载。
第一次发生这种情况,sys.modules['urllib3.packages.six']
还不存在,导入机器找到文件 urllib3/packages/six.py
,导入它,before 它'我会寻找更多的名字。
而且,正如您发现的那样,导入 six.py
模块文件的行为导致该模块添加 sys.modules['urllib3.packages.six.moves']
和对标准库模块的进一步引用。
Python 的进口机械相当复杂; Python 参考文档在 The import system 中全面介绍了这一点;要查找的具体条目是:
以下A direct call to
__import__()
performs only the module search and, if found, the module creation operation. While certain side-effects may occur, such as the importing of parent packages, and the updating of various caches (including sys.modules), only the import statement performs a name binding operation.
Importing
parent.one
will implicitly executeparent/__init__.py
andparent/one/__init__.py.
Subsequent imports ofparent.two
orparent.three
will executeparent/two/__init__.py
andparent/three/__init__.py
respectively.
及The module cache以下:
The first place checked during import search is
sys.modules
. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So iffoo.bar.baz
was previously imported,sys.modules
will contain entries forfoo
,foo.bar
, andfoo.bar.baz
. Each key will have as its value the corresponding module object.
(我添加的引用部分中的粗体强调)。
请注意 urllib3/packages
目录中的所有内容都是 vendorized 包;一个通常会独立安装的项目,但 urllib3
项目决定将其与自己的发行版打包在一起,以避免担心支持哪些版本。 six
就是这样一个独立的项目,可以安装from PyPI.
您可以在 six.moves
virtual package in the six
project documentation 上找到更多信息。它的目的是让库开发人员更容易编写与 Python 2 和 Python 3 兼容的代码,而不必担心在任一版本上导入什么标准库名称。
Python 中关于导入函数的一个值得注意的事情是,它不仅可以导入模块本身,还可以从其中导入变量、classes、函数(通常是名称空间)。 在示例中,您提供了:
from .packages.six.moves.http_client import (
IncompleteRead as httplib_IncompleteRead
)
import 语句引用 src/urllib3/packages/six.py
模块中的 moves 变量,该变量在该文件的第 316 行定义并分配给 class 的实例_MovedItems:
moves = _MovedItems(__name__ + ".moves")
和http_client是一个属性或这个class实例的方法