花了一些時間研究,雖然還是搞不太懂怎麼樣用相對路徑匯入模組
不過至少純以專案內自己的絕對路徑,目前實驗是可以運作的~。
這裡主要的參考資料是 [1],我的實驗程式的架構如下:
~/ python/ module1/ __init__.py x.py module2/ __init.py y.py main.py所有的程式碼都放在 ~/python 這個資料夾中,有兩個模組 module1 和 module2,並且 __init__.py 全都是空的。
以下是三個 .py 檔的內容。
main.py
from module1.x import ModuleX print("main.py is running under %s" % __name__) print("main.py: Call module X's class") ModuleX().run()
module1/x.py
from module2.y import ModuleY class ModuleX: def run(self): print("Module X is running under %s" % __name__) print("x.py: Call Module Y") ModuleY().run()
module1/y.py
class ModuleY: def run(self): print("Module Y is running under %s" % __name__)
要執行以上的程式時,會使用以下的指令:
python ~/python/main.py
簡要說明一下,Main.py 會去呼叫 module1 資料夾裡的 x.py 定義的類別
x.py 又會透過匯入(import)的方式,匯入另一個資料夾 module2 的模組 y.py,並呼叫 y.py 裡面定義的類別。
而本文的重點就是 x.py 如何匯入 y.py 了~這裡使用的方式是軟體內的絕對路徑
也就是以執行的進入點 main.py 作為最上層(top level)的模組根目錄
x 模組的位置就會是 module1.x、y 模組的位置則是 module2.y。
比較詳細的說明,或許可以參考看看 [2-3]
關鍵點好像在於 Python 有個 __name__ 的設定,根據官方文件 [3] 關於relative import 的說明,有著以下的特性:
Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.我目前的理解是,每個模組都有個隱藏的 __name__ 屬性,會記錄這個模組在模組的樹狀結構中的位置
這個屬性會在模組被匯入時,會自動填入模組的名稱與路徑
而如果模組是程式進入點,__name__ 屬性會被填入 "__main__",並且會成為樹狀結構中的樹根
這種狀況下,程式進入點的 .py 檔是沒有辦法匯入非自己的子模組的其他模組的~。
這也說明了,在 [2] 中的回應,為何網友 Andrew Clark 說 relative import 只能用在被匯入的模組上。
最後,上述的程式碼的執行結果如下:
main.py is running under __main__ main.py: Call module X's class Module X is running under module1.x x.py: Call Module Y Module Y is running under module2.y可以看出,main.py 的 __name__ 被設定為 "__main__",表示程式進入點以及模組樹的樹根
而以 main.py 為樹根的樹狀結構中,x.py 的 __name__ 即為 "module1.x"、y.py 的 __name 則為 "module2.y"。
參考資料:
沒有留言:
張貼留言