python import坑總結(jié)
如果所有代碼都在同一個(gè)目錄,一切都簡(jiǎn)單而美好。
然而一旦源碼分目錄,目錄內(nèi)的代碼需要讓目錄外訪問(wèn),那就沒(méi)有完美方案。
pf
│? m4.py
│? __init__.py
├─pa
│? ? ? m1.py
│? ? ? m2.py
│? ? ? __init__.py
└─pb
? ? ? ? m3.py
? ? ? ? __init__.py
m2引用m1
m3引用m2
m4引用m2
問(wèn)題的根源在于:
????1 每次我們寫import xx的時(shí)候,注意此時(shí)開(kāi)頭沒(méi)有./../...這樣的相對(duì)路徑,都是相對(duì)于__main__的路徑的,不是run python時(shí)的啟動(dòng)路徑的,也不是文件自身。也就是說(shuō),從m3和m4分別作為_(kāi)_main__引用m2時(shí),m2內(nèi)不能簡(jiǎn)單寫from m1。因?yàn)閜b和pf內(nèi)都沒(méi)有m1。
????2 當(dāng)我們寫from .xx/..xx?import yy時(shí),是相對(duì)于文件自身,但是這個(gè)文件就不能直接作為_(kāi)_main__直接執(zhí)行了。因?yàn)?/..要先查找上級(jí),然而__main__沒(méi)有上級(jí),本身就是根了。這是個(gè)必須面對(duì)的問(wèn)題,直接執(zhí)行的能力對(duì)于小項(xiàng)目,或者就是日常實(shí)驗(yàn)的小玩具,是很方便的?;蛘邚膖oy逐步長(zhǎng)成project是很自然的。
方案1:
????m2內(nèi)寫from pa.m1
????好處,m4都能引用m2。
????代價(jià)1,m2文件對(duì)pa目錄的名稱產(chǎn)生了依賴,甚至依賴于直到自己在工程中的完整層級(jí)路徑,即使保持m1在m2同目錄內(nèi)。
????代價(jià)2,m2本身不能作為_(kāi)_main__直接執(zhí)行了,因?yàn)閟ys.path包pa含但不包含pf,在pa路徑下是找不到pa自己的。
????代價(jià)3,m3依然不能引用m2,因?yàn)閜b內(nèi)沒(méi)有pa。
方案1a:
????在方案1的基礎(chǔ)上,修正代價(jià)2,3。在m2內(nèi)的最開(kāi)始增加代碼:
????????import sys
????????import os
????????sys.path[0]=os.path.abspath(".")#不替代的話,append,insert也行,重名問(wèn)題。
????并且,所有__main__都在pf這一級(jí)執(zhí)行。本質(zhì)是將import的根路徑從__main__替換成了python的啟動(dòng)路徑。
????這使得當(dāng)我們?cè)趐f內(nèi)執(zhí)行python pa/m2.py是,sys.path中不只有pa還有pf。
????注意重名問(wèn)題。
方案2:
????m2內(nèi)寫from .m1。
????好處,m2不需要知道m(xù)1所在的路徑叫啥名了。只要m1和m2保持在同一目錄就行。
????代價(jià),m2徹底不能作為_(kāi)_main__執(zhí)行了,根沒(méi)有父也就沒(méi)有兄。原直接執(zhí)行功能需要挪到新文件中。
????探討,這里如果python能像python -m一樣,虛擬一個(gè)包含所有同級(jí)module的父節(jié)點(diǎn)就好了,這是最接近大家直觀需求和其他語(yǔ)言簡(jiǎn)單情況的行為;以文件的視角思考,而非以項(xiàng)目根目錄的角度思考。
方案3:
????使用namespace
????未完待續(xù)。。。