urllib3中的相对导入

时间:2018-10-18 20:13:31

标签: python python-import

我正在研究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.pysrc/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

我尝试使用__name__全局变量,如建议的here所示。其值为urllib3.packages.six,但urllib3.packages不会加载该文件。

2 个答案:

答案 0 :(得分:3)

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,并在之前导入,它将寻找更多名称

而且,正如您所发现的那样,导入six.py模块文件的行为使该模块添加了sys.modules['urllib3.packages.six.moves']并进一步引用了标准库模块。

Python的导入机制相当复杂。 Python参考文档在The import system中对此进行了全面介绍;要查找的特定条目是:

  

直接调用__import__()仅执行模块搜索,如果找到,则执行模块创建操作。尽管可能会发生某些副作用,例如,例如,导入父包,以及更新各种缓存(包括sys.modules),但只有import语句执行名称绑定操作。

并在Regular packages

  

导入parent.one将隐式执行parent/__init__.pyparent/one/__init__.py.,随后导入parent.twoparent.three将执行parent/two/__init__.pyparent/three/__init__.py分别。

The module cache下:

  

在导入搜索期间检查的第一位是sys.modules。此映射充当所有先前导入的模块的缓存,包括中间路径。因此,如果先前导入了foo.bar.baz,则sys.modules将包含foofoo.barfoo.bar.baz的条目。每个键都有对应的模块对象作为其值。

(我在加引号的部分中大胆强调)。

请注意,urllib3/packages目录中的所有内容都是 vendorized 包;通常可以独立安装的项目,但是urllib3项目已决定将其与自己的发行版打包在一起,从而不必担心要支持哪些版本。 six是一个独立的项目,您可以安装from PyPI

您可以在six.moves virtual packagesix project documentation中找到更多信息。目的是使库开发人员更轻松地编写与Python 2和Python 3兼容的代码,而不必担心在任何一个版本上导入哪个标准库名称。

答案 1 :(得分:0)

关于Python中的导入函数的一个值得注意的事情是,它不仅可以导入模块本身,还可以从模块内部导入变量,类,函数(通常是名称空间)。 在示例中,您提供了:

from .packages.six.moves.http_client import (
  IncompleteRead as httplib_IncompleteRead
)

import语句引用src/urllib3/packages/six.py模块中的 moves 变量,该变量在该文件的第316行定义,并分配给类 _MovedItems 的实例:

moves = _MovedItems(__name__ + ".moves")

http_client 是此类实例的属性或方法

相关问题