[英]Relative import in urllib3
我正在研究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
不會加載該文件。
在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
模塊文件的six.py
操作使該模塊添加sys.modules['urllib3.packages.six.moves']
以及對標准庫模塊的進一步引用。
Python的導入機制非常復雜。 Python參考文檔在Import系統中對此進行了全面介紹; 要查找的特定條目是:
直接調用
__import__()
僅執行模塊搜索,如果找到,則執行模塊創建操作。 雖然可能會發生某些副作用, 例如,導入父包以及更新各種緩存(包括sys.modules),但只有import語句執行名稱綁定操作。
並在常規套餐下
導入
parent.one
將隱式執行parent/__init__.py
和parent/one/__init__.py.
隨后導入parent.two
或parent.three
將分別執行parent/two/__init__.py
和parent/three/__init__.py
。
並在模塊緩存下 :
導入搜索期間檢查的第一位是
sys.modules
。 該映射充當先前已導入的所有模塊( 包括中間路徑)的緩存。 因此,如果先前導入了foo.bar.baz
,則sys.modules
將包含foo
,foo.bar
和foo.bar.baz
條目。 每個鍵都有對應的模塊對象作為其值。
(在我添加的引用部分中大膽強調)。
請注意, urllib3/packages
目錄中的所有內容都是供應商提供的軟件包。 一個通常可以獨立安裝的項目,但urllib3
項目已決定將其與自己的發行版打包在一起,從而不必擔心要支持哪些版本。 six
是這樣一個獨立的項目,您可以從PyPI安裝它。
您可以在six
項目文檔中找到有關six.moves
虛擬包的更多信息。 目的是使庫開發人員可以更輕松地編寫與Python 2和Python 3兼容的代碼,而不必擔心在任何一個版本上導入哪個標准庫名稱。
關於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是此類實例的屬性或方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.