10.3 使用相對(duì)路徑名導(dǎo)入包中子模塊

2018-02-24 15:27 更新

問題

將代碼組織成包,想用import語(yǔ)句從另一個(gè)包名沒有硬編碼過的包的中導(dǎo)入子模塊。

解決方案

使用包的相對(duì)導(dǎo)入,使一個(gè)的模塊導(dǎo)入同一個(gè)包的另一個(gè)模塊 舉個(gè)例子,假設(shè)在你的文件系統(tǒng)上有mypackage包,組織如下:

mypackage/
    __init__.py
    A/
        __init__.py
        spam.py
        grok.py
    B/
        __init__.py
        bar.py

如果模塊mypackage.A.spam要導(dǎo)入同目錄下的模塊grok,它應(yīng)該包括的import語(yǔ)句如下:

# mypackage/A/spam.py
from . import grok

如果模塊mypackage.A.spam要導(dǎo)入不同目錄下的模塊B.bar,它應(yīng)該使用的import語(yǔ)句如下:

# mypackage/A/spam.py
from ..B import bar

兩個(gè)import語(yǔ)句都沒包含頂層包名,而是使用了spam.py的相對(duì)路徑。

討論

在包內(nèi),既可以使用相對(duì)路徑也可以使用絕對(duì)路徑來導(dǎo)入。 舉個(gè)例子:

# mypackage/A/spam.py
from mypackage.A import grok # OK
from . import grok # OK
import grok # Error (not found)

像mypackage.A這樣使用絕對(duì)路徑名的不利之處是這將頂層包名硬編碼到你的源碼中。如果你想重新組織它,你的代碼將更脆,很難工作。 舉個(gè)例子,如果你改變了包名,你就必須檢查所有文件來修正源碼。 同樣,硬編碼的名稱會(huì)使移動(dòng)代碼變得困難。舉個(gè)例子,也許有人想安裝兩個(gè)不同版本的軟件包,只通過名稱區(qū)分它們。 如果使用相對(duì)導(dǎo)入,那一切都o(jì)k,然而使用絕對(duì)路徑名很可能會(huì)出問題。

import語(yǔ)句的?<span class="pre" style="box-sizing: border-box;">.</span>?和?``..``看起來很滑稽, 但它指定目錄名.為當(dāng)前目錄,..B為目錄../B。這種語(yǔ)法只適用于import。 舉個(gè)例子:

from . import grok # OK
import .grok # ERROR

盡管使用相對(duì)導(dǎo)入看起來像是瀏覽文件系統(tǒng),但是不能到定義包的目錄之外。也就是說,使用點(diǎn)的這種模式從不是包的目錄中導(dǎo)入將會(huì)引發(fā)錯(cuò)誤。

最后,相對(duì)導(dǎo)入只適用于在合適的包中的模塊。尤其是在頂層的腳本的簡(jiǎn)單模塊中,它們將不起作用。如果包的部分被作為腳本直接執(zhí)行,那它們將不起作用 例如:

% python3 mypackage/A/spam.py # Relative imports fail

另一方面,如果你使用Python的-m選項(xiàng)來執(zhí)行先前的腳本,相對(duì)導(dǎo)入將會(huì)正確運(yùn)行。 例如:

% python3 -m mypackage.A.spam # Relative imports work

更多的包的相對(duì)導(dǎo)入的背景知識(shí),請(qǐng)看?PEP 328?.

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)