如何避免Python的循環(huán)導(dǎo)入問題

本文首載于Gevin的博客
未經(jīng)Gevin授權(quán)糕非,禁止轉(zhuǎn)載
原文鏈接:如何避免Python的循環(huán)導(dǎo)入問題

how to avoid python circle import error

Python 中使用package時澎办,出現(xiàn)循環(huán)導(dǎo)入問題十分常見馆里,我們創(chuàng)建如下package來說明這個問題:

pkg
  ├── __init__.py
  ├── module_a.py
  └── module_b.py

其中羹应,

  • __init__.pypkg指定為一個Python package
  • module_a.py中定義了一個action_a()函數(shù)倚评,該函數(shù)引用了module_b.py中的一個attribute,如一個函數(shù)或變量
  • module_b.py中定義了一個action_b()函數(shù)单鹿,該函數(shù)引用了module_a.py中的一個attribute掀宋,如一個函數(shù)或變量

這種情況下,執(zhí)行該package時會拋出circular import error錯誤仲锄,即循環(huán)引用劲妙,因為module_a試圖去引入module_b時,而module_b首先要引入module_a儒喊,這會導(dǎo)致Python解釋器無法執(zhí)行下去镣奋。

然而,我們可以通過一些巧妙的方法怀愧,讓上面的邏輯正常工作唆途,同時避免循環(huán)引入的錯誤富雅。

那么,什么時候它能正常工作肛搬,什么時候不能正常工作,而那些能夠正常工作的情況又是什么原因呢毕贼?

何時它能正常工作温赔?

1. 在module頂部引入,不要用from鬼癣,相對引入陶贼,只在Python 2中有效

在module的頂部import,如import another_module待秃,module 中的函數(shù)以another_module.attribute的方式引用another_module中的函數(shù)或變量等拜秧。這種方式之所以有效,是由于import another_module是基于當(dāng)前目錄的相對引用章郁,而且是一種隱式引用枉氮,如果從另一個package中引入module時,就可以失效了暖庄。另外聊替,import another_module這種語法在Python 3 中已經(jīng)不支持了,所以不要在代碼中用這種方法來避免循環(huán)引入培廓。

如:

# pkg/module_a.py 
from __future__ import print_function
import module_b

def action_a():
    print(module_b.action_b.__name__)


# pkg/module_b.py
from __future__ import print_function
import module_a

def action_b():
    print(module_a.action_a.__name__)

2. 在module的頂部引入惹悄,不要用from,絕對引入

在module的頂部import肩钠,使用從package開始的絕對路徑泣港,如import package.another_module,module 中的函數(shù)以package.another_module.attribute的方式引用another_module中的函數(shù)或變量等价匠。之所以要掛上package name來引入当纱,是由于import .another_module這種形式的“相對引入”會報語法錯誤,而掛上package的絕對引入霞怀,Python 2和3都支持

案例:

# pkg/module_a.py
from __future__ import print_function
import pkg2.module_b

def action_a():
    print(pkg2.module_b.action_b.__name__)


# pkg/module_b.py
from __future__ import print_function
import pkg2.module_a

def action_b():
    print(pkg2.module_a.action_a.__name__)

    

3. 在module底部引入another module的attribute惫东,而非another module,用from

在module的底部import(至少要在被引用的attribute之后import)毙石,直接引入another module的attribute廉沮,如from package.another_module import attribute,相對引入也支持徐矩,如from .another_module import attribute滞时,module中的函數(shù)直接使用被引用的attribute即可。

如:

# pkg/module_a.py
from __future__ import print_function

def action_a():
    print(action_b.__name__)

from .module_b import action_b


# pkg/module_b.py
from __future__ import print_function

def action_b():
    print(action_a.__name__)

from .module_a import action_a

4. 函數(shù)頂部引入滤灯,可以用from

在module的function頂部import坪稽,如from package import another_module曼玩,也支持相對引入,引入module或attribute均可窒百。

如:

# pkg/module_a.py
from __future__ import print_function

def action_a():
    from . import module_b
    print(module_b.action_b.__name__)


# pkg/module_b.py
from __future__ import print_function

def action_b():
    from . import module_a
    print(module_a.action_a.__name__)

# pkg/module_a.py
from __future__ import print_function

def action_a():
    from .module_b import action_b
    print(action_b.__name__)


# pkg/module_b.py
from __future__ import print_function
def action_b():
    from .module_a import action_a
    print(action_a.__name__)


這種方式雖然Python 2和3都支持黍判,但編碼不夠優(yōu)雅,影響代碼可讀性篙梢,不建議使用

  • 本文討論的問題顷帖,是Python中調(diào)用package時,應(yīng)如何避免循環(huán)引入
  • 當(dāng)直接在命令行執(zhí)行一個Python module時渤滞,適用情況不完全相同
  • 本文內(nèi)容我在GitHub上提供了一個Demo贬墩,歡迎查看或fork
  • Reference:This Gist
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市妄呕,隨后出現(xiàn)的幾起案子陶舞,更是在濱河造成了極大的恐慌,老刑警劉巖绪励,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肿孵,死亡現(xiàn)場離奇詭異,居然都是意外死亡优炬,警方通過查閱死者的電腦和手機颁井,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蠢护,“玉大人雅宾,你說我怎么就攤上這事】叮” “怎么了眉抬?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長懈凹。 經(jīng)常有香客問我蜀变,道長,這世上最難降的妖魔是什么介评? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任库北,我火速辦了婚禮,結(jié)果婚禮上们陆,老公的妹妹穿的比我還像新娘寒瓦。我一直安慰自己,他們只是感情好坪仇,可當(dāng)我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布杂腰。 她就那樣靜靜地躺著,像睡著了一般椅文。 火紅的嫁衣襯著肌膚如雪喂很。 梳的紋絲不亂的頭發(fā)上惜颇,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天,我揣著相機與錄音少辣,去河邊找鬼凌摄。 笑死,一個胖子當(dāng)著我的面吹牛毒坛,可吹牛的內(nèi)容都是我干的望伦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼煎殷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腿箩?” 一聲冷哼從身側(cè)響起豪直,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珠移,沒想到半個月后弓乙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡钧惧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年暇韧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浓瞪。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡懈玻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乾颁,到底是詐尸還是另有隱情涂乌,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布英岭,位于F島的核電站湾盒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诅妹。R本人自食惡果不足惜罚勾,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吭狡。 院中可真熱鬧尖殃,春花似錦、人聲如沸赵刑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽般此。三九已至蚪战,卻和暖如春牵现,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背邀桑。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工瞎疼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壁畸。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓贼急,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捏萍。 傳聞我的和親對象是個殘疾皇子太抓,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,700評論 2 345

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

  • 個人筆記,方便自己查閱使用 Py.LangSpec.Contents Refs Built-in Closure ...
    freenik閱讀 67,678評論 0 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理令杈,服務(wù)發(fā)現(xiàn)走敌,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評論 25 707
  • 小學(xué)時逗噩〉衾觯“小徐子,去給爺爺我買瓶可樂异雁〈氛希”我在椅子上翹個二郎腿說道「俚叮“峰…峰哥项炼,我是真…真難得沒錢啦你就別讓我去了。...
    戰(zhàn)毀星辰閱讀 264評論 0 0
  • 故事要有連續(xù)性柑蛇,有彈性芥挣。有一個連續(xù)的故事主線連著全局。 故事是這樣的:A大學(xué)畢業(yè)慢慢的進入社會耻台,學(xué)習(xí)的是廣告的設(shè)計...
    導(dǎo)演張升志閱讀 240評論 0 0