python之import機(jī)制

1. 標(biāo)準(zhǔn) import

Python 中所有加載到內(nèi)存的模塊都放在 sys.modules 断凶。當(dāng) import 一個(gè)模塊時(shí)首先會(huì)在這個(gè)列表中查找是否已經(jīng)加載了此模塊讹蘑,如果加載了則只是將模塊的名字加入到正在調(diào)用 import 的模塊的 Local 名字空間中鼠渺。如果沒有加載則從 sys.path 目錄中按照模塊名稱查找模塊文件提前,模塊可以是py崇渗、pyc、pyd急前,找到后將模塊載入內(nèi)存醒陆,并加到 sys.modules 中,并將名稱導(dǎo)入到當(dāng)前的 Local 名字空間裆针。

一個(gè)模塊不會(huì)重復(fù)載入刨摩。多個(gè)不同的模塊都可以用 import 引入同一個(gè)模塊到自己的 Local 名字空間,其實(shí)背后的 PyModuleObject 對(duì)象只有一個(gè)据块。說一個(gè)容易忽略的問題:import 只能導(dǎo)入模塊码邻,不能導(dǎo)入模塊中的對(duì)象(類、函數(shù)另假、變量等)。例如:模塊 A(A.py)中有個(gè)函數(shù) getName怕犁,另一個(gè)模塊不能通過 import A.getName 將 getName導(dǎo)入到本模塊边篮,只能用 fromA import getName。

2. 嵌套 import

1)順序嵌套

例如:本模塊導(dǎo)入 A 模塊(import A)奏甫,A 中又 import B戈轿,B 模塊又可以 import 其他模塊……

這中嵌套比較容易理解,需要注意的一點(diǎn)就是各個(gè)模塊的 Local 名字空間是獨(dú)立的阵子。對(duì)于上面的例子思杯,本模塊 import A 之后本模塊只能訪問模塊 A,不能訪問模塊 B 及其他模塊挠进。雖然模塊 B 已經(jīng)加載到內(nèi)存了色乾,如果訪問還要再明確的在本模塊中 import B。

2)循環(huán)嵌套

例如:文件[ A.py ]

from B import D

class C:pass

文件[ B.py ]

from A import C

class D:pass

為什么執(zhí)行 A 的時(shí)候不能加載 D 呢领突?

如果將 A.py 改為:import B 就可以了暖璧。

這是怎么回事呢?

RobertChen:這跟Python內(nèi)部 import 的機(jī)制是有關(guān)的君旦,具體到 from B import D澎办,Python 內(nèi)部會(huì)分成幾個(gè)步驟:

(1)在 sys.modules 中查找符號(hào) “B”

(2)如果符號(hào) B 存在,則獲得符號(hào) B 對(duì)應(yīng)的 module 對(duì)象金砍。

從 的 __dict__ 中獲得符號(hào) “D” 對(duì)應(yīng)的對(duì)象局蚀,如果 “D” 不存在,則拋出異常恕稠。

(3)如果符號(hào) B 不存在琅绅,則創(chuàng)建一個(gè)新的 module 對(duì)象 ,注意谱俭,此時(shí)奉件,module 對(duì)象的 __dict__ 為空宵蛀。

執(zhí)行 B.py 中的表達(dá)式,填充的 __dict__县貌。

從的 __dict__ 中獲得 “D” 對(duì)應(yīng)的對(duì)象术陶,如果 “D” 不存在,則拋出異常煤痕。

所以這個(gè)例子的執(zhí)行順序如下:

1梧宫、執(zhí)行 A.py 中的 from B import D 由于是執(zhí)行的 python A.py,所以在 sys.modules 中并沒有 存在摆碉, 首先為 B.py 創(chuàng)建一個(gè) module 對(duì)象 () 塘匣, 注意,這時(shí)創(chuàng)建的這個(gè) module 對(duì)象是空的巷帝,里邊啥也沒有忌卤, 在 Python 內(nèi)部創(chuàng)建了這個(gè) module 對(duì)象之后,就會(huì)解析執(zhí)行 B.py楞泼,其目的是填充 這個(gè) __dict__驰徊。

2、執(zhí)行 B.py中的from A import C 在執(zhí)行B.py的過程中堕阔,會(huì)碰到這一句棍厂, 首先檢查sys.modules這個(gè)module緩存中是否已經(jīng)存在了, 由于這時(shí)緩存還沒有緩存超陆, 所以類似的牺弹,Python內(nèi)部會(huì)為A.py創(chuàng)建一個(gè)module對(duì)象(), 然后时呀,同樣地张漂,執(zhí)行A.py中的語句

3、再次執(zhí)行A.py中的from B import D 這時(shí)退唠,由于在第1步時(shí)鹃锈,創(chuàng)建的對(duì)象已經(jīng)緩存在了sys.modules中, 所以直接就得到了瞧预, 但是屎债,注意,從整個(gè)過程來看垢油,我們知道盆驹,這時(shí)還是一個(gè)空的對(duì)象,里面啥也沒有滩愁, 所以從這個(gè)module中獲得符號(hào)"D"的操作就會(huì)拋出異常躯喇。 如果這里只是import B,由于"B"這個(gè)符號(hào)在sys.modules中已經(jīng)存在,所以是不會(huì)拋出異常的廉丽。

ZQ:圖解

啄木鳥社區(qū)《import 迷宮》:http://wiki.woodpecker.org.cn/moin/MiscItems/2008-11-25

3. 包 import

只要一個(gè)文件夾下面有個(gè) __init__.py 文件倦微,那么這個(gè)文件夾就可以看做是一個(gè)包。包導(dǎo)入的過程和模塊的基本一致正压,只是導(dǎo)入包的時(shí)候會(huì)執(zhí)行此包目錄下的__init__.py而不是模塊里面的語句了欣福。另外,如果只是單純的導(dǎo)入包焦履,而包的 __init__.py 中又沒有明確的其他初始化操作拓劝,那么此包下面的模塊是不會(huì)自動(dòng)導(dǎo)入的。

例如:

有下面的包結(jié)構(gòu):PA

|---- __init__.py

|---- wave.py

|---- PB1

|---- __init__.py

|---- pb1_m.py

|---- PB2

|---- __init__.py

|---- pb2_m.py

有如下程序:

import sys

import PA.wave#1

import PA.PB1#2

import PA.PB1.pb1_m as m1#3

import PA.PB2.pb2_m#4

PA.wave.getName()#5

m1.getName()#6

PA.PB.pb2_m.getName()#7

1) 當(dāng)執(zhí)行 #1 后嘉裤,sys.modules 會(huì)同時(shí)存在 PA郑临、PA.wave 兩個(gè)模塊,此時(shí)可以調(diào)用 PA.wave 的任何類或函數(shù)了屑宠。但不能調(diào)用 PA.PB1(2) 下的任何模塊厢洞。當(dāng)前 Local 中有了 PA 名字。

2) 當(dāng)執(zhí)行 #2 后典奉,只是將 PA.PB1 載入內(nèi)存犀变,sys.modules 中會(huì)有 PA、 PA.wave秋柄、PA.PB1 三個(gè)模塊,但是 PA.PB1 下的任何模塊都沒有自動(dòng)載入內(nèi)存蠢正,此時(shí)如果直接執(zhí)行 PA.PB1.pb1_m.getName() 則會(huì)出錯(cuò)骇笔,因?yàn)?PA.PB1 中并沒有 pb1_m 。當(dāng)前 Local 中還是只有 PA 名字嚣崭,并沒有 PA.PB1 名 字笨触。

3) 當(dāng)執(zhí)行 #3 后,會(huì)將 PA.PB1 下的 pb1_m 載入內(nèi)存雹舀,sys.modules 中會(huì)有 PA芦劣、PA.wave、PA.PB1说榆、PA.PB1.pb1_m 四個(gè)模塊虚吟,此時(shí)可以執(zhí)行 PA.PB1.pb1_m.getName() 了。由于使用了 as签财,當(dāng)前 Local中除了 PA 名字串慰,另外添加了 m1 作為 PA.PB1.pb1_m 的別名。

4) 當(dāng)執(zhí)行 #4 后唱蒸,會(huì)將 PA.PB2邦鲫、PA.PB2.pb2_m 載入內(nèi)存,sys.modules 中會(huì)有 PA神汹、PA.wave庆捺、PA.PB1古今、PA.PB1.pb1_m、PA.PB2滔以、PA.PB2.pb2_m 六個(gè)模塊捉腥。當(dāng)前 Local 中還是只有 PA、m1醉者。

下面的 #5但狭,#6,#7 都是可以正確運(yùn)行的撬即。

注意的是:如果 PA.PB2.pb2_m 想導(dǎo)入 PA.PB1.pb1_m立磁、PA.wave 是可以直接成功的。最好是采用明確的導(dǎo)入路徑剥槐,對(duì)于 ./.. 相對(duì)導(dǎo)入路徑還是不推薦用唱歧。

原文:http://blog.csdn.net/zbyufei/article/details/5894645

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市粒竖,隨后出現(xiàn)的幾起案子颅崩,更是在濱河造成了極大的恐慌,老刑警劉巖蕊苗,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沿后,死亡現(xiàn)場離奇詭異,居然都是意外死亡朽砰,警方通過查閱死者的電腦和手機(jī)尖滚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞧柔,“玉大人漆弄,你說我怎么就攤上這事≡旃” “怎么了撼唾?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長哥蔚。 經(jīng)常有香客問我倒谷,道長,這世上最難降的妖魔是什么肺素? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任恨锚,我火速辦了婚禮,結(jié)果婚禮上倍靡,老公的妹妹穿的比我還像新娘猴伶。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布他挎。 她就那樣靜靜地躺著筝尾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪办桨。 梳的紋絲不亂的頭發(fā)上筹淫,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音呢撞,去河邊找鬼损姜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛殊霞,可吹牛的內(nèi)容都是我干的摧阅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼绷蹲,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼棒卷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起祝钢,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤比规,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拦英,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜒什,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年疤估,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吃谣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡做裙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肃晚,到底是詐尸還是另有隱情锚贱,我是刑警寧澤,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布关串,位于F島的核電站拧廊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏晋修。R本人自食惡果不足惜吧碾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望墓卦。 院中可真熱鬧倦春,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呢堰,卻和暖如春抄瑟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枉疼。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國打工皮假, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骂维。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓惹资,卻偏偏與公主長得像,于是被迫代替她去往敵國和親席舍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子布轿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • python中經(jīng)常用到模塊,比如import xxx,from xxx import yyy這樣子来颤,里面的機(jī)制也是...
    __七把刀__閱讀 3,240評(píng)論 0 6
  • 不知道什么時(shí)候開始汰扭,一直有一句話一直掛在口中:”哎,早習(xí)慣了一個(gè)人的生活福铅÷苊”到底是什么開始的,自己也不知道滑黔,習(xí)慣了...
    暮夜之歌閱讀 415評(píng)論 0 1
  • Good morning/afternoon, First, I would like to thank you ...
    496Vincent閱讀 229評(píng)論 0 1
  • 也可稱的上高富帥的王阿蒙1988年生笆包,2011年從某省會(huì)城市還算不錯(cuò)的二本航空院校畢業(yè)。畢業(yè)后他應(yīng)聘到家鄉(xiāng)西北的A...
    周龍王閱讀 634評(píng)論 0 0