[python] ImportError: Attempted relative import

當直接run某個.py文件,而這個.py文件中有諸如:

from . import x

from .. import y

的導入語句時,就會報上述相對路徑錯誤。

根源可歸結為下面一句話:

Relative imports use a module’s name attribute to determine that module’s position in the package hierarchy.

也就是說,相對路徑是根據(jù)當前module的名稱屬性來決定所導入的相對模塊的位置的。

首先我們回顧一下絕對導入(即導入時的module名不以.開頭)的搜尋路徑(python 2.7文檔6.1.2 The Module Search Path有詳細闡述)。

1、built-in模塊

2、在sys.path指定的目錄中查找。sys.path在啟動python解釋器時按照下面的順序初始化

a、當前運行腳本所在的目錄

b、PYTHONPATH(即標準庫,類似于'C:\\WINDOWS\\SYSTEM32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Python27',)

c、安裝依賴的一些缺省值(類似于C:\\Python27\\lib\\site-packages)

你可以在代碼中修改sys.path的值來改變搜尋路徑,比如sys.path.append( "/specified/path"),當然也許你想將這個特定的搜尋路徑放在sys.path的開頭,這樣具有更高的優(yōu)先級,可以這樣做sys.path.insert(0, "/specified/path")。

話說回來,相對導入是根據(jù)當前module的名稱屬性來決定所導入的相對模塊的位置的,也就是根據(jù)當前module的__name__屬性來計算相對導入模塊的位置,如果你直接運行module.py(a.k.a python module.py),那么當前module.py的__name__屬性值為"__main__"(比如你經(jīng)常在其中添加 if __name__ == "__main__": do_something()),顯然根據(jù)"__main__"來計算相對路徑肯定得不到你想要的結果。

假設如下的代碼層次結構:

package/

? ? __init__.py

? ? subpackage1/

? ? ? ? __init__.py

? ? ? ? moduleX.py(from .. import moduleA)

? ? moduleA.py

run.py (import package.subpackage1.moduleX)

如果python run.py,則運行到moduleX中時,moduleX的__name__屬性值就是package.subpackage1.moduleX,這時根據(jù)導入,會得到package.subpackage1.moduleX..moduleA,即package.subpackage1.moduleA也是準確的。

簡而言之,當你運行某個python文件時,這個python腳本最好處于你的代碼的頂部(top-level),且該python腳本都采用絕對路徑導入(因為該python腳本的__name__此時是"__main__",仍無法使用相對路徑)。在底層的目錄中的python腳本就可以使用.開頭的相對路徑了。但要注意的是,為了采用相對路徑能找到對應的module,目錄中必須有__init__.py,這才會構造成一個package,即便__init__.py是個空文件!

一個繞過上述規(guī)則的方法(https://www.python.org/dev/peps/pep-0366/): __package__. When it is present, relative imports will be based on this attribute rather than the module __name__ attribute。你可以在代碼中這樣寫:

if __name__ == "__main__" and __package__ is None:

? ? __package__ = "expected.package.name"

即明確為module指所屬的package名稱。

參考:

1、https://blog.csdn.net/qiusuoxiaozi/article/details/79061885

2、https://www.python.org/dev/peps/pep-0366/

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 當前目錄 和 腳本目錄 參考資料:https://techibee.com/python/get-current-...
    ThomasYoungK閱讀 11,876評論 0 11
  • 小魚低語閱讀 191評論 1 1
  • 2018年5月1日 星期二 桑吉巴爾島 大雨 曾經(jīng)以為一生很漫長,長得看不到盡頭。驀然回首,卻突然發(fā)現(xiàn),時光已一點...
    都市虎妞閱讀 418評論 6 9
  • 父親開朗、幽默。父親和叔叔、2個姑媽關系融洽,經(jīng)常是正經(jīng)的事情不正經(jīng)的說,不正經(jīng)的事情正經(jīng)的說,因此大家庭里多了不...
    行者無疆頌閱讀 201評論 0 0
  • 皮亞杰認為人的心理發(fā)展是以年齡為參照,以認知發(fā)展最終形成運算為目的。 于是,他把認知發(fā)展分為四個重要的階段,在每個...
    恰如初閱讀 193評論 0 0

友情鏈接更多精彩內容