python 相对导入_python 相对导入与绝对导入
Python 相對(duì)導(dǎo)入與絕對(duì)導(dǎo)入
Python | Jul 21, 2016 | python
Python 相對(duì)導(dǎo)入與絕對(duì)導(dǎo)入,這兩個(gè)概念是相對(duì)于包內(nèi)導(dǎo)入而言的。包內(nèi)導(dǎo)入即是包內(nèi)的模塊導(dǎo)入包內(nèi)部的模塊。
Python import 的搜索路徑
1.在當(dāng)前目錄下搜索該模塊
2.在環(huán)境變量 sys.path 中指定的路徑列表中依次搜索
3.在 Python 安裝路徑的 lib 庫中搜索
Python import 的步驟
python 所有加載的模塊信息都存放在 sys.modules 結(jié)構(gòu)中,當(dāng) import 一個(gè)模塊時(shí),會(huì)按如下步驟來進(jìn)行
如果是 import A,檢查 sys.modules 中是否已經(jīng)有 A,如果有則不加載,如果沒有則為 A 創(chuàng)建 module 對(duì)象,并加載 A
如果是 from A import B,先為 A 創(chuàng)建 module 對(duì)象,再解析A,從中尋找B并填充到 A 的 dict 中
相對(duì)導(dǎo)入與絕對(duì)導(dǎo)入
絕對(duì)導(dǎo)入的格式為 import A.B 或 from A import B,相對(duì)導(dǎo)入格式為 from . import B 或 from ..A import B,.代表當(dāng)前模塊,..代表上層模塊,...代表上上層模塊,依次類推。
相對(duì)導(dǎo)入可以避免硬編碼帶來的維護(hù)問題,例如我們改了某一頂層包的名,那么其子包所有的導(dǎo)入就都不能用了。但是 存在相對(duì)導(dǎo)入語句的模塊,不能直接運(yùn)行,否則會(huì)有異常:
ValueError: Attempted relative import in non-package
這是什么原因呢?我們需要先來了解下導(dǎo)入模塊時(shí)的一些規(guī)則:
在沒有明確指定包結(jié)構(gòu)的情況下,Python 是根據(jù) name 來決定一個(gè)模塊在包中的結(jié)構(gòu)的,如果是 main 則它本身是頂層模塊,沒有包結(jié)構(gòu),如果是A.B.C 結(jié)構(gòu),那么頂層模塊是 A。基本上遵循這樣的原則:
如果是絕對(duì)導(dǎo)入,一個(gè)模塊只能導(dǎo)入自身的子模塊或和它的頂層模塊同級(jí)別的模塊及其子模塊
如果是相對(duì)導(dǎo)入,一個(gè)模塊必須有包結(jié)構(gòu)且只能導(dǎo)入它的頂層模塊內(nèi)部的模塊
如果一個(gè)模塊被直接運(yùn)行,則它自己為頂層模塊,不存在層次結(jié)構(gòu),所以找不到其他的相對(duì)路徑。
Python2.x 缺省為相對(duì)路徑導(dǎo)入,Python3.x 缺省為絕對(duì)路徑導(dǎo)入。絕對(duì)導(dǎo)入可以避免導(dǎo)入子包覆蓋掉標(biāo)準(zhǔn)庫模塊(由于名字相同,發(fā)生沖突)。如果在 Python2.x 中要默認(rèn)使用絕對(duì)導(dǎo)入,可以在文件開頭加入如下語句:
from future import absolute_import
from future import absolute_import
這句 import 并不是指將所有的導(dǎo)入視為絕對(duì)導(dǎo)入,而是指禁用 implicit relative import(隱式相對(duì)導(dǎo)入), 但并不會(huì)禁掉 explicit relative import(顯示相對(duì)導(dǎo)入)。
那么到底什么是隱式相對(duì)導(dǎo)入,什么又是顯示的相對(duì)導(dǎo)入呢?我們來看一個(gè)例子,假設(shè)有如下包結(jié)構(gòu):
thing
├── books
│ ├── adventure.py
│ ├── history.py
│ ├── horror.py
│ ├── __init__.py
│ └── lovestory.py
├── furniture
│ ├── armchair.py
│ ├── bench.py
│ ├── __init__.py
│ ├── screen.py
│ └── stool.py
└── __init__.py
那么如果在 stool 中引用 bench,則有如下幾種方式:
import bench # 此為 implicit relative import
from . import bench # 此為 explicit relative import
from furniture import bench # 此為 absolute import
隱式相對(duì)就是沒有告訴解釋器相對(duì)于誰,但默認(rèn)相對(duì)與當(dāng)前模塊;而顯示相對(duì)則明確告訴解釋器相對(duì)于誰來導(dǎo)入。以上導(dǎo)入方式的第三種,才是官方推薦的,第一種是官方強(qiáng)烈不推薦的,Python3 中已經(jīng)被廢棄,這種方式只能用于導(dǎo)入 path 中的模塊。
相對(duì)與絕對(duì)僅針對(duì)包內(nèi)導(dǎo)入而言
最后再次強(qiáng)調(diào),相對(duì)導(dǎo)入與絕對(duì)導(dǎo)入僅針對(duì)于包內(nèi)導(dǎo)入而言,要不然本文所討論的內(nèi)容就沒有意義。所謂的包,就是包含 init.py 文件的目錄,該文件在包導(dǎo)入時(shí)會(huì)被首先執(zhí)行,該文件可以為空,也可以在其中加入任意合法的 Python 代碼。
相對(duì)導(dǎo)入可以避免硬編碼,對(duì)于包的維護(hù)是友好的。絕對(duì)導(dǎo)入可以避免與標(biāo)準(zhǔn)庫命名的沖突,實(shí)際上也不推薦自定義模塊與標(biāo)準(zhǔn)庫命令相同。
前面提到含有相對(duì)導(dǎo)入的模塊不能被直接運(yùn)行,實(shí)際上含有絕對(duì)導(dǎo)入的模塊也不能被直接運(yùn)行,會(huì)出現(xiàn) ImportError:
ImportError: No module named XXX
這與絕對(duì)導(dǎo)入時(shí)是一樣的原因。要運(yùn)行包中包含絕對(duì)導(dǎo)入和相對(duì)導(dǎo)入的模塊,可以用 python -m A.B.C 告訴解釋器模塊的層次結(jié)構(gòu)。
有人可能會(huì)問:假如有兩個(gè)模塊 a.py 和 b.py 放在同一個(gè)目錄下,為什么能在 b.py 中 import a 呢?
這是因?yàn)檫@兩個(gè)文件所在的目錄不是一個(gè)包,那么每一個(gè) python 文件都是一個(gè)獨(dú)立的、可以直接被其他模塊導(dǎo)入的模塊,就像你導(dǎo)入標(biāo)準(zhǔn)庫一樣,它們不存在相對(duì)導(dǎo)入和絕對(duì)導(dǎo)入的問題。相對(duì)導(dǎo)入與絕對(duì)導(dǎo)入僅用于包內(nèi)部。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的python 相对导入_python 相对导入与绝对导入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地下城与勇士怎么开副职业
- 下一篇: python1~10阶乘while_Py