成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Python Package Import 之痛

nihao / 1885人閱讀

摘要:所以,解決方案是強(qiáng)制要求從整個(gè)項(xiàng)目的頂層用來設(shè)置端正的路徑。這個(gè)做法是官方推薦的,也是合邏輯的,即一個(gè)完整的項(xiàng)目運(yùn)行就應(yīng)當(dāng)以項(xiàng)目為入口來運(yùn)行所有的子或子。經(jīng)過不斷的實(shí)踐,發(fā)現(xiàn)他們大都沒說清楚上下文,甚至沒有告訴完整的解決方案。

參考Python官方:Packages
?參考:Python相對導(dǎo)入一處不解
參考:使用相對路徑名導(dǎo)入包中子模塊

理解Package

Python里,就像所有的.py文件被稱為Module模塊一樣,所有的文件夾都被稱為Package包。前提是,這個(gè)文件夾里有一個(gè)__init__.py文件,可以是空文件也可以有一些方便都內(nèi)容。

一旦一個(gè)文件夾可以被視為Package,那么其中的所有文件都會(huì)有獨(dú)立的Namespace命名空間,即變量都不共享,與其它的package完全獨(dú)立。一個(gè)項(xiàng)目里,可以有很多個(gè)子文件夾、子子文件夾,一旦變成package,那么它們都能互相獨(dú)立,方便我們引用。

理解sys.path
Python的目錄結(jié)構(gòu)中,“向當(dāng)前腳本以下的目錄import”永遠(yuǎn)不會(huì)出問題,出問題的,總是“向上一層目錄import”

在Python的運(yùn)行一個(gè).py腳本的時(shí)候,會(huì)自動(dòng)將sys.path設(shè)置為腳本所在目錄。然后凡是這個(gè)sys.path之下的所有的文件模塊,都能直接import導(dǎo)入。
但是,很明顯的,只有這個(gè).py腳本之內(nèi)的目錄才包括在path里,也就是說它之外的所有事情它都一無所知。相當(dāng)于Linux shell中的PATH。

在Python的導(dǎo)入邏輯里,非常/非常/非常重要的一點(diǎn)必須時(shí)時(shí)刻刻記在心上:
啟動(dòng)腳本所在的目錄,將持續(xù)作為當(dāng)前目錄來運(yùn)行所有導(dǎo)入的模塊。

也就是說,如果你要導(dǎo)入另一文件夾的模塊,而那個(gè)模塊依賴于它同級(jí)目錄的一個(gè)模塊,這個(gè)時(shí)候它是不能直接導(dǎo)入同級(jí)目錄模塊的!因?yàn)楫?dāng)前的path已經(jīng)變了!

比如,目錄結(jié)構(gòu)如下:

Project
├── __init__.py
├── main.py
├── sub1
│?? ├── __init__.py
│?? ├── common1.py
│?? ├── mod1.py *
└── sub2
    ├── __init__.py
    ├── common2.py
    └── mod2.py *

假設(shè),我們在mod1.py中使用from common1 import *來引用同級(jí)目錄的sub1/common1.py
同時(shí),我們在mod2.py中使用from common2 import *來引用同級(jí)目錄的sub2/common2.py
另外,我們在mod1.py中需要導(dǎo)入mod2.py。(先略過具體實(shí)現(xiàn)方法)

那么問題出現(xiàn)了:
當(dāng)我用$ python mod1.py時(shí)候,當(dāng)前的path是project/sub1/,導(dǎo)入mod2.py后,它在執(zhí)行from common2 ...的時(shí)候,理所當(dāng)然的是找不到的,因?yàn)閟ub1中沒有common2.py這個(gè)文件!

理解Python模塊的相對引用和絕對引用

那么現(xiàn)在,我們應(yīng)該做什么呢?改變mod2.py中的導(dǎo)入路徑嗎?
當(dāng)然不行!我們不能隨便改一個(gè)Package的導(dǎo)入邏輯,如果這個(gè)package是別的作者寫的怎么辦?如果改了以后,那個(gè)package以自身為入口時(shí)候運(yùn)行怎么辦?這些全都會(huì)亂套。

所以,解決方案是:

強(qiáng)制要求從整個(gè)項(xiàng)目的頂層用python -m project.sub1.mod1來設(shè)置端正的PATH路徑。 然后其它所有子模塊、子包都用from project.sub2 import mod2這樣的完整項(xiàng)目引用的語句來導(dǎo)入。

這個(gè)做法是PEP官方推薦的,也是合邏輯的,即:
一個(gè)完整的項(xiàng)目運(yùn)行就應(yīng)當(dāng)以項(xiàng)目為入口來運(yùn)行所有的子module子package。
如果又想讓某個(gè)子package被同項(xiàng)目的其它子package引用,又想多帶帶運(yùn)行,那就應(yīng)當(dāng)徹底把它從文件夾里抽離出來變成一個(gè)多帶帶的“第三方庫”來用。

那么具體應(yīng)該怎么修改各個(gè)文件中的導(dǎo)入語句呢:

刪除每個(gè)文件中的相對引用,如from common1 import *。

改為項(xiàng)目級(jí)別的絕對引用,如:from project.sub2 import mod2

如果需要運(yùn)行/測試某個(gè)子模塊的文件,需要cd切換到項(xiàng)目目錄的再上一層中,執(zhí)行:python -m project.sub1.mod1。注意,這里的命名是包/模塊式的,不能以.py結(jié)尾!

Sibling Package Imports 父目錄中的同級(jí)目錄導(dǎo)入

具體問題來了:怎么導(dǎo)入父級(jí)目錄中的其它模塊或包呢?

再復(fù)習(xí)一下我們的目錄結(jié)構(gòu):

Project
├── main.py
├── sub1
│?? ├── common.py
│?? ├── mod1.py *
└── sub2
    ├── common.py
    └── mod2.py *

目的:在sub1/mod1.py中,導(dǎo)入sub2/mod2.py。同時(shí),mod2.py中還需要導(dǎo)入同目錄的common.py才能工作。

這是一個(gè)項(xiàng)目里再正常不過的操作了,可是如果你嘗試google一下的話,可能會(huì)花費(fèi)你數(shù)小時(shí),結(jié)果還是讓你自己的大腦Stack-overflow.

目前stackoverflow會(huì)有人提供這幾種hacks來實(shí)現(xiàn)我們的目的:

mod1.py中用sys.path.append("..")來把父級(jí)目錄加到path中引用

from ..sub2 import mod2來實(shí)現(xiàn)相對引用

直接from project.sub2 import mod2

__init__.py進(jìn)行一些path設(shè)定或import導(dǎo)入。

經(jīng)過不斷的實(shí)踐,發(fā)現(xiàn)他們大都沒說清楚上下文,甚至沒有告訴完整的解決方案。
總結(jié)出的經(jīng)驗(yàn)就是:以上的那些hacks終究是hacks,不是官方推薦的,也不能真正派上用場。

比如sys.path.append()方法,一開始似乎走通了不報(bào)錯(cuò)。但是真實(shí)項(xiàng)目走起來,比不可能給每個(gè)文件都加一句sys.path.append()。走到最后,你用print( sys.path )會(huì)發(fā)現(xiàn)path中莫名其妙多了很多很多路徑。這肯定不行,也沒見過任何項(xiàng)目源碼里這么寫的。

再比如from ..sub2 import *這樣的相對引用,能這么用的上下文必須是:執(zhí)行腳本時(shí)要是從文件夾頂級(jí)入口執(zhí)行,如果直接從mod1.py執(zhí)行腳本,那么這句話是會(huì)報(bào)錯(cuò)的。

所以還是用官方推薦的方法和邏輯,丟棄那些hacks吧。

要達(dá)到sibling imports,在這個(gè)例子里,具體做法是:

修改所有的模塊mod1.py和mod2.py,把導(dǎo)入語句改為from project.sub? import mod?這樣的。

如果要導(dǎo)入具體某個(gè)模塊中的類或函數(shù),則:from project.sub?.mod? import MyClass

執(zhí)行子包中的某個(gè)子模塊時(shí),cd到project目錄再往上一層,輸入python -m project.sub1.mod1執(zhí)行

執(zhí)行整個(gè)項(xiàng)目的話,就python -m project

__init____all__ 限制導(dǎo)入模塊

參考Python官方: Importing ? From a Package

Python規(guī)定:
如果在一個(gè)package包中的__init__.py中寫上__all__ = ["模塊1", "模塊2", "模塊3"]的話,
那么在其它模塊引用這個(gè)package包使用from PACKAGE import *這種用法的時(shí)候,
不會(huì)真的引用包中所有的模塊(那樣會(huì)很耗內(nèi)存),而只能導(dǎo)入作者在__all__里規(guī)定的模塊。

__init____path__ 多層次目錄導(dǎo)入

參考Python官方:Packages in Multiple Directories

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/43083.html

相關(guān)文章

  • 告別webpack react 搭建多頁面之痛

    摘要:搭建多頁面應(yīng)用在往下看之前請確保先上個(gè)涼的吃著目錄結(jié)構(gòu)編譯結(jié)果配置文件腳本存放處項(xiàng)目開發(fā)中一些常用的方法主要存放和請求有關(guān)的靜態(tài)文件模版文件項(xiàng)目開發(fā)中一些常用的方法其實(shí)我覺得可以和放在一塊,但是個(gè)人習(xí)慣還是分開啦開始擼代碼如何創(chuàng)建多頁面應(yīng)用 webpack4 搭建 react 多頁面應(yīng)用 在往下看之前請確保nodejs > 8.X 先上個(gè)涼的吃著 目錄結(jié)構(gòu) . ├── dist ...

    seanHai 評論0 收藏0
  • unicode之痛【精校版】

    摘要:之痛原文地址譯者校正實(shí)用編程指南這是我在所做的演講。事實(shí)一和二共同造成了計(jì)算機(jī)設(shè)備結(jié)構(gòu)與世界人類需求的一個(gè)沖突。就是為了解決之前的老的字符集問題。值意味著,失敗時(shí)將會(huì)返回一個(gè)標(biāo)準(zhǔn)的替代字符。將使用進(jìn)行了解碼。 Unicode之痛原文地址: http://nedbatchelder.com/text...譯者: yudun1989 校正: sicklife實(shí)用Unicode編程指南這是...

    zombieda 評論0 收藏0
  • python import 機(jī)制初探

    摘要:引子考慮有如下代碼結(jié)構(gòu)情況其余文件為空。分析情況當(dāng)我們運(yùn)行時(shí),這時(shí)候系統(tǒng)的搜素路徑包括,我們可以通過在中添加證實(shí)這一點(diǎn)。情況情況其實(shí)和情況很不一樣,情況叫做,也就是包內(nèi)間接引用。顧名思義,這種引用方法只能在包內(nèi)使用。都是,但不一定是。 引子 考慮有如下代碼結(jié)構(gòu) . ├── cat │?? ├── __init__.py │?? ├── cat.py │?? └── moo.py └──...

    leanxi 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<