我正在研究python是如何加载模块的。
我从加载urllib3的requests开始。
我找到了那条线
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吗?
我尝试过使用__name__全局变量(如建议的这里 )。它的值是urllib3.packages.six,但urllib3.packages不加载该文件。
发布于 2018-10-18 20:25:31
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参考文档在https://docs.python.org/3/reference/import.html#regular-packages中全面介绍了这一点;要查找的具体条目如下:
对
__import__()的直接调用只执行模块搜索,如果找到,则执行模块创建操作。虽然可能会发生某些副作用,但(例如导入父包)和更新各种缓存(包括sys.modules)时,只有导入语句执行名称绑定操作。
以及在https://docs.python.org/3/reference/import.html#regular-packages下
导入
parent.one将隐式执行parent/__init__.py和parent/one/__init__.py.,随后的parent.two或parent.three导入将分别执行parent/two/__init__.py和parent/three/__init__.py。
以及在https://docs.python.org/3/reference/import.html#the-module-cache下
在导入搜索期间检查的第一个位置是
sys.modules。此映射用作以前导入的所有模块(包括中间路径)的缓存。因此,如果以前导入了foo.bar.baz,sys.modules将包含foo、foo.bar和foo.bar.baz的条目。每个键都将有相应的模块对象作为其值。
(我所加的引文部分以粗体强调)。
请注意,urllib3/packages目录中的所有内容都是一个供应商化的包;这个项目通常是独立安装的,但是urllib3项目已经决定将其打包到自己的发行版中,以避免担心要支持哪个版本。six是一个如此独立的项目,您可以安装它来自PyPI。
您可以在虚拟包中找到关于项目文件的更多信息。它的目的是使库开发人员能够更容易地编写与Python 2和Python 3兼容的代码,而不必担心在这两个版本上导入什么标准库名称。
发布于 2018-10-18 20:34:59
Python中导入函数的一个值得注意的地方是,它不仅可以导入模块本身,还可以从模块内部导入变量、类、函数(通常是名称空间)。在本例中,您提供了:
from .packages.six.moves.http_client import (
IncompleteRead as httplib_IncompleteRead
)导入语句是指将变量从src/urllib3/packages/six.py模块中移出,该模块定义在该文件的第316行,并分配给类_MovedItems的实例。
moves = _MovedItems(__name__ + ".moves")http_client是该类实例的属性或方法。
https://stackoverflow.com/questions/52881839
复制相似问题