目錄結構
.
├── apt_root.py
├── __init__.py
├── mod/
└── test.py
└── __init__.py
└── sub/
└── test.py
└── __init__.py
任務一:在mod/test.py中import 上級目錄下的apt_root.py
任務二:在mod/test.py中import 上級目錄的sub/test.py
前提
【爲什麼題目限定python3的import?】
因爲網上能搜到的PEP都是python2的。例如PEP328。但是據我觀察,python2和python3的import規則不同。
【絕對路徑他不香嗎,爲什麼限定用相對路徑import模塊?】
通過絕對路徑引用模塊,容易造成在後續改變代碼結構,或者文件改名時,修改工作多的問題。而相對路徑沒有這個問題
解析
寫這篇文章的一個出發點,是我發現import並沒有很簡單,至少對我造成了很多混亂,因此在這裏進行分享,希望能上面兩個任務能覆蓋所有困難情況。首先一個混亂,是用不同方式執行test.py,其中的import能不能找到對應module是不同的。
用python test.py的方式
這時,在根目錄下執行python mod/test.py ,
或者 進入mod子目錄再執行python test.py的效果是一樣的。
用網上查到的這些方式都會報錯:
from . import apt_root
# 或者
from .. import apt_root
# 或者
from ..apt_root import *
我測試成功的寫法是這樣:
import sys
sys.path.append(".")
import app_root
所以,應該一個‘.’是上一級目錄,兩個'.'是上兩級。意思是把上一級目錄加入搜索路徑。
用python -m test的方式
這種方式下,如果我的import是這樣:
import app_root
(和直接python xxx.py不同)在不同目錄下運行,會有不同效果!
一:在根目錄下:python -m mod.test——運行成功
二:先進入mod子目錄,再python -m test——運行失敗
如果要運行成功,則應該這樣:
sys.path.append("..")
import app_root
(又一個造成混亂的)python -m xxx時,把上級目錄加入搜索路徑,要用"..",這和python xxx.py時,用"."代表上級目錄不同!
原因是python -m方式,會把當前運行命令的路徑添加至sys.path。參見[python]自問自答:python -m參數?
所以,這種方法下,一定要結合當前運行命令的路徑+默認sys.path中搜索路徑+代碼中sys.path.append新增路徑,才能判斷import是否能成功。
總結
容易造成混亂的地方:
1.相對路徑的使用不能用from .. import XX,而要用sys.path.append(“..”)
2.python -m xxx和python xxx.py對import的寫法中上級目錄表示不同,前者用兩個點,後者用一個點;
3.python -m xxx中import搜索路徑與當前執行命令的目錄相關;
python xxx.py與當前執行命令的目錄無關
【歡迎關注我的微信公衆號:人工智能Beta】