python 解釋器搜索package 模塊過程
模塊:每一個python文件都是一個模塊。
當執行import module時,解釋器會根據下面的搜索路徑,搜索module1.py文件。
1) 當前工作目錄
2) PYTHONPATH中的目錄
3) Python安裝目錄 (/usr/local/lib/python)
事實上,模塊搜索是在保存在sys.path這個全局變量中的目錄列表中進行搜索。
package是模塊的集合,每一個Package的根目錄下面都應當有一個__init__.py 文件。當解釋器發現目錄下有這個文件時,他就會認為這是一個Package,而不是一個普通的目錄。
示例:通過兩種方法來實現包機制,主要區別在於是否在 __init__.py 中寫入模塊導入語句
目錄結構如下:
[root@dev home]# tree package_transfer/ package_transfer/ ├── demo.py ├── __init__.py ├── package01 │ ├── classOne.py │ └── __init__.py └── package02 ├── classTwo.py └── __init__.py
第一種調用方式 : __init__.py 是一個空白文件
1.在主入口文件里面調用。
classOne.py 內容如下:
from package02.classTwo import classTwo class classOne: def __init__(self): self.name = "class one" def printInfo(self): print("i am class One!")
classTwo.py 內容如下:
class classTwo: def __init__(self): self.name = "class two" def printInfo(self): print("i am class two!")
主入口文件:demo.py 內容如下
from package01.classOne import classOne from package02.classTwo import classTwo if __name__ == "__main__": c1 = classOne() c1.printInfo() c2 = classTwo() c2.printInfo() # 運行結果: # i am class One! # i am class two!
因為 此時的demo.py 文件和 package01,package02 在同一層目錄下,因此,可以直接調用包下面的模塊方法。
2.加入 classOne.py 要去調用 package02 下的文件 classTwo 里面的方法。
import os,sys BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #這里是把頂層目錄加入到python的環境變量中。 sys.path.append(BASE_DIR) from package02.classTwo import classTwo class classOne: def __init__(self): self.name = "class one" def printInfo(self): print("i am class One!") if __name__ == "__main__": c2 = classTwo() c2.printInfo() # 運行結果: # i am class two!
第二種調用方式:在__init__.py 下面寫入包的信息。
還是上面的目錄和內容:
在 packge01/__init__.py 中添加:
import sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from package01.classOne import classOne
在 packge02/__init__.py 中添加:
import sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from package02.classTwo import classTwo
在 demo.py 文件中就可以這樣寫:
import package01 import package02 if __name__ == "__main__": c1 = package01.classOne() c1.printInfo() c2 = package02.classTwo() c2.printInfo() # 運行結果: # i am class One! # i am class two!
還可以這樣導入:
from package01 import * from package02 import * if __name__ == "__main__": c1 = classOne() c1.printInfo() c2 = classTwo() c2.printInfo() # 執行結果 # i am class One! # i am class two!
如果不在上面的 __init__.py 文件中寫入信息。如果直接導入,那么會報如下錯誤:
import package01 import package02 if __name__ == "__main__": c1 = package01.classOne() c1.printInfo() c2 = package02.classTwo() c2.printInfo() # 運行結果: # Traceback (most recent call last): # File "D:/gitcode/...../package_transfer/demo.py", line 21, in <module> # c1 = package01.classOne() # AttributeError: module 'package01' has no attribute 'classOne'
記憶:所有的模塊的引入,在__init__.py 里面的路徑應該寫到當前project 的頂層目錄,這樣在調用的時候 就能夠清晰明了的導入自己想要導入的模塊。