一、絕對引用
首先總結一下import的各種姿勢:
1、import package 讀這個包的__init__.py
2、import module 讀這個模塊全部內容
3、import package1.package2.package3.module4 讀package1, package2, package3的__init__.py, 以及module4全部內容(順序)
4、import package1.package2 讀 package1, package2的__init__.py(順序)
這些是import中發生的事情。情況1、2沒什么好說的,直接用package.或者module.就可以了。
情況3中,假設package1下有package2, package22, package222三個包,還有一個module2222模塊,你想訪問除了package2之外的其他東西,如果在所有的__init__.py中沒有引用他們,那么調用是會出錯的。
在情況3中,sys.modules會加入以下的模塊
'package1'
'package1.package2'
'package1.package2.package3'
'package1.package2.package3.module4'
你嘗試着看package1,或者調用package1.abc (abc在__init__中定義),這是可以成功的。
接着上面情況3的例子,現在你用
from package1.package2.package3 import module4
與之前一樣,這些包的__init__也會運行
sys.modules與上述也相同
但是!神奇的地方來了!package1和package1.abc解釋器並不認識!
原因是什么呢?猜測系統的邏輯如下:
import 1.2.3.4 那么你可能會用到1, 1.2, 1.2.3, 1.2.3.4, 系統默認都記下來
from 1.2.3 import 4,那么看起來你只會用到4, 那么1干脆就忘掉算了。但是1確實是跑過的,計算的東西都有,只不過並沒有1並沒有
絕對引用中的問題
import x1.x2報錯找不到?
每次Import x1.xxx的時候,都是要讀x1.__init__.py的,如果沒有該文件,那么就無法導入啦。
所以,如果第一層是個文件夾,一定要保證這個文件夾中有__init__.py文件!否則既不能import x1.x2, 也不能from x1 import x2。總之你就是無法得到x2,除非把x1加入到python環境變量PYTHONPATH中。
二、相對引用
從點和兩點開始的引用,都是相對引用。
我們把相對引用存在的文件叫引用模塊,
相對引用注意事項
1、相對引用發生在package內部,引用模塊那一級一定要有__init__.py
2、調用的腳本的位置一定要在package外,如果腳本在引用模塊那一級,實際上是找不到上一級的東西的,會報錯。
ValueError: Attempted relative import in non-package。
3、使用相對引用的模塊,不能直接作為腳本跑,否則會報錯
ValueError: Attempted relative import in non-package。
解決方法一: import 該腳本
解決方法二:python -m 該腳本,也類似import。
相對引用原理
stackoverflow中有解釋:relative import依賴文件__name__,而如果跑那個腳本的話,文件名字就成了__main__,這樣__package__會被設為None,而相對引用依賴__package__的值,就找不到相對引用的位置了,會報Non-package的錯誤,在命令行中可以用-m跑,意思是把它當作一個模塊。
三、根據名稱import
按道理使用__import__函數即可,python對此特意進行了封裝,成為importlib.import_module函數
該函數如果使用相對引用,需要給package參數,package名稱和sys.modules中的名稱相同即可