简体   繁体   English

urllib3中的相对导入

[英]Relative import in urllib3

I'm studying how python loads modules. 我正在研究python如何加载模块。

I'm starting from requests that loads urllib3 . 我从加载urllib3 requests开始。

I have found those line : 我找到了这些行

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

in file called src/urllib3/exceptions.py 在名为src/urllib3/exceptions.py

That import is a relative one, so I'm looking for the folder src/urllib3/packages/six/moves/http_client.py or src/urllib3/packages/six/moves/http_client/__init__.py 该导入是一个相对的导入,因此我正在寻找文件夹src/urllib3/packages/six/moves/http_client.pysrc/urllib3/packages/six/moves/http_client/__init__.py

Those files don't exist. 这些文件不存在。

Thankfully src/urllib3/packages/six.py defines a new module loader, so the import .packages.six.moves.http_client requires http_client core python module instead. 幸运的是src/urllib3/packages/six.py定义了一个新的模块加载器,因此导入.packages.six.moves.http_client需要使用http_client核心python模块。

But I don't understand how the src/urllib3/packages/six.py is loaded. 但是我不明白src/urllib3/packages/six.py是如何加载的。 I've not found that kind of import. 我没有找到这种导入。

Is there a way to know which module loads src/urllib3/packages/six.py directly? 有没有办法知道哪个模块直接加载src/urllib3/packages/six.py

I have tried with __name__ global variable as suggested here . 我已经尝试使用__name__全局变量,如这里建议的那样。 Its value is urllib3.packages.six but urllib3.packages doesn't load that file. 其值为urllib3.packages.sixurllib3.packages不会加载该文件。

The from .packages.six.moves.http_client import ... expression causes .packages.six to be loaded first . from .packages.six.moves.http_client import ...表达导致.packages.six 首先被加载。 Python always loads all packages in a nested package reference to a module. Python始终将所有软件包加载到模块的嵌套软件包引用中。

So .packages.six.moves.http_client causes Python first to look for urllib3.packages , then for urllib3.packages.six , and so on. 因此.packages.six.moves.http_client使Python首先查找urllib3.packages ,然后查找urllib3.packages.six ,依此类推。 The import machinery does so by looking for the full name in sys.modules , and if it is not there, triggers a module search and load for each. 导入机制通过在sys.modules查找全名来进行此操作,如果不存在全名,则会触发模块搜索并为每个模块加载。

The first time this happens, sys.modules['urllib3.packages.six'] doesn't exist yet, the import machinery finds the file urllib3/packages/six.py , imports that, before it'll look for more names. 第一次发生这种情况时, sys.modules['urllib3.packages.six']尚不存在,导入机制会找到文件urllib3/packages/six.py然后在寻找更多名称之前对其进行导入。

And, as you discovered, the very act of importing the six.py module file, causes that module to add sys.modules['urllib3.packages.six.moves'] and further references to standard library modules. 而且,正如您所发现的,导入six.py模块文件的six.py操作使该模块添加sys.modules['urllib3.packages.six.moves']以及对标准库模块的进一步引用。

Python's import machinery is quite a complex beast; Python的导入机制非常复杂。 the Python reference documentation covers this comprehensively in The import system ; Python参考文档在Import系统中对此进行了全面介绍; the specific entries to look for are: 要查找的特定条目是:

A direct call to __import__() performs only the module search and, if found, the module creation operation. 直接调用__import__()仅执行模块搜索,如果找到,则执行模块创建操作。 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. 虽然可能会发生某些副作用, 例如,导入父包以及更新各种缓存(包括sys.modules),但只有import语句执行名称绑定操作。

and under Regular packages 并在常规套餐下

Importing parent.one will implicitly execute parent/__init__.py and parent/one/__init__.py. 导入parent.one将隐式执行parent/__init__.pyparent/one/__init__.py. Subsequent imports of parent.two or parent.three will execute parent/two/__init__.py and parent/three/__init__.py respectively. 随后导入parent.twoparent.three将分别执行parent/two/__init__.pyparent/three/__init__.py

and under The module cache : 并在模块缓存下

The first place checked during import search is sys.modules . 导入搜索期间检查的第一位是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 . 因此,如果先前导入了foo.bar.baz ,则sys.modules将包含foofoo.barfoo.bar.baz条目。 Each key will have as its value the corresponding module object. 每个键都有对应的模块对象作为其值。

(bold emphasis in quoted sections added by me). (在我添加的引用部分中大胆强调)。

Note that everything in the urllib3/packages directory is a vendorized package; 请注意, urllib3/packages目录中的所有内容都是供应商提供的软件包。 a project that normally would be installed independently, but which the urllib3 project has decided to package up with their own distribution to avoid having to worry about what versions to support. 一个通常可以独立安装的项目,但urllib3项目已决定将其与自己的发行版打包在一起,从而不必担心要支持哪些版本。 six is such an independent project, you can install it from PyPI . six是这样一个独立的项目,您可以从PyPI安装它。

You can find more information on the six.moves virtual package in the six project documentation . 您可以在six项目文档中找到有关six.moves虚拟包的更多信息。 It's purpose is to make it easier for library developers to write code that is compatible both with Python 2 and Python 3, without having to worry about what standard library name to import on either version. 目的是使库开发人员可以更轻松地编写与Python 2和Python 3兼容的代码,而不必担心在任何一个版本上导入哪个标准库名称。

One notable thing about import function in Python is that it can import not only modules themselves but also variables, classes, functions (generally namespaces) from inside them. 关于Python中的导入功能的一件值得注意的事情是,它不仅可以导入模块本身,还可以从模块内部导入变量,类,函数(通常是名称空间)。 In the example, you have provided: 在示例中,您提供了:

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

import statement refers to moves variable from src/urllib3/packages/six.py module, which is defined at line 316 of that file and being assigned to an instance of class _MovedItems : import语句引用src/urllib3/packages/six.py模块中的moves变量,该变量在该文件的第316行定义,并分配给_MovedItems类的实例:

moves = _MovedItems(__name__ + ".moves")

and http_client is a property or method of this class instance 并且http_client是此类实例的属性或方法

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

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