python包相對導入

  • 絕對路徑導入格式爲import a.b或者from a import b,相對路徑導入格式爲from . import b或者from ..a import bpython

  • python2默認爲相對路徑導入,python3默認爲絕對路徑導入。git

  • 爲使python2,3通用,建議採用相對路徑導入from .a import bgithub

  • 一個目錄存在__init__.py文件,則該目錄成爲一個包。shell

  • 包中的一個模塊能夠採用相對路徑導入包,不影響模塊功能;一個py腳本(未成爲模塊,即其目錄及父目錄內無__init__.py)能夠採用相對路徑導入包,並以腳本模式運行。但包含相對導入的模塊,不能直接以腳本模式運行,常見報錯爲:app

# python2
Traceback (most recent call last):    File "module_x.py", line 1, in <module>      from . module_y import spam as ham  ValueError: Attempted relative import in non-package
# python3
Traceback (most recent call last):    File "module_x.py", line 1, in <module>      from . module_y import spam as ham  SystemError: Parent module '' not loaded, cannot perform relative import

解決方案:

創建示例文件結構以下:
注:以/結尾的爲文件夾。spa

/home/zhkai/
            mobike/
                  __init__.py
                  utils.py
                  data_process/
                          loc.py

注意此時mobike成爲一個python包。
loc.py中導入utils.py該怎麼辦?code

方法1:將mobike包導入系統路徑

loc.py中導入util的方法爲:orm

import sys
sys.path.append('/home/zhkai')
from mobike.utils import read_csv

須要注意,這裏導入系統路徑的是mobike所在目錄的路徑,路徑自己不包含mobike。
此時utils就像自帶的python包同樣,loc.py可直接運行。ip

【推薦】方法2:修改運行命令

python的man page裏有這個參數:get

-m module-name 
   Searches  sys.path for the named module and runs the corresponding .py file as a script.

因此能夠在不修改模塊代碼文件的狀況下:
代碼文件仍爲相對路徑:

from ..utils import read_csv

切換到mobike包同級目錄下執行:

☁  ~  python3 -m mobike.data_process.loc

注意:此時若loc.py代碼中有其餘相對路徑,此時的相對路徑是基於shell命令所在位置,即~的,可能會形成錯誤。import語句中的相對路徑,還是基於文件所在位置,故不影響。

推薦這種方法,由於無需修改代碼文件。

還有句話不太理解:
若是一個模塊被直接運行,則它本身爲頂層模塊,不存在層次結構,因此找不到其餘的相對路徑。


參考:
Python 相對導入與絕對導入

相關文章
相關標籤/搜索