python 的 import 使用規則


對於含有 __init__.py 的目錄(如adir),其實它就是一個package,它的子目錄如果也包含 __init__.py,則只要將 adir 加入 sys.path,則它的字目錄就不用加了,python在import的時候會自動遍歷所有含有 __init__.py 的子目錄。

 

python文件的引入有2中方式:1、作為頂層執行腳本(執行入口)而加載;2、作為模塊被引入。如果你直接執行一個python文件,則它就被當作頂層執行腳本而被加載。如果你使用參數-m (python -m file.py),則該文件被當作模塊被引入,  如果該文件被其它文件以import的方式引入,則它也會被當成模塊。一個文件的引入方式只能是這兩種中的一種,而且某時刻只能是其中一種。

介紹了import,就必須介紹python的naming:

當文件被裝載之后,它就會在裝載器中獲得一個唯一的命名,變量叫做 __name__。如果文件作為頂層執行腳本被引入,則 __name__ == "__main__"。如果作為module被引入,則 __name__ 就是文件的文件名加上一些前綴,這些前綴就是packages/subpackages這樣的類似文件路徑的東西,不過是由點號dot隔開,而不是/隔開。注意其中的“類似”兩字,表明前綴和文件路徑不完全一樣。比如:

package/ __init__.py subpackage1/ __init__.py moduleX.py moduleA.py

如果你引入(即作為模塊被引入) moduleX,則它的 __name__ 就是 package.subpackage1.moduleX,如果你引入moduleA,則它的 __name__ 就是package.moduleA。但是如果你直接執行moduleX,則它的 __name__就是 "__main__",如果你直接執行moduleA,它的名字就變成了 "__main__",模塊名 package.moduleA 自動被舍棄。

作為模塊引入的時候,__name__ 屬性是隨引入的方式而不同的。一般有2種方式:被同級目錄里的其它文件引用,或經由package而被引用。以上面例子為例,如果被同級目錄里的文件引用,則moduleX的 __name__ 屬性為 "moduleX",而不是 "package.subpackage1.moduleX"。因為python會將當前目錄自動加入search path,它並不知道自己所在的目錄是否屬於某packge。一個特例是,如果你使用的是交互式python命令行,則該命令行的session的 __name__ 屬性為 "__main__"

因此,綜上所述,你引入一個module的方式(經由同級目錄里的其它文件引用,或經由package引用,也即 __name__ 屬性的值)是你能否將一個文件module成功引入的關鍵。

 

相對引入:

由於python為了保證package作為一個獨立的模塊,即將它拷貝到別處也不依賴於模塊外部的東西而能馬上運行,因此相對引入不允許引入package外的任何東西。

因此,相對引入有一下規則:

相對引入是使用module的 __name__ 屬性來判定它是否屬於一個package或在某package的位置。如果你使用相對引入如 from .. import foo,則這里的 .. 是告訴python從當前目錄開始反向搜索本package去搜索 foo 模塊(向本package的頂層回溯兩個dot)。以上面的例子為例,如果當前模塊的 __name__ 是 package.subpackage1.moduleX,則 ..moduleA 就意味着將找到 package.moduleA。為了 .. import 正確工作,模塊的 __name__ 必須擁有相應個數的dot,如 package.subpackage1.moduleX 模塊,向左數兩個dot,則是package模塊

如果你當前module的 __name__ 是 "__main__",則python會認為該module不在任何package中(即便它在),因為__name__中不包含dot,因此你無法在其文件中使用 .. import,也即無法使用 相對引入,否則你會得到"relative-import in non-package" 錯誤提示。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM