python的import是在程序運行期間執行的,并非像其它很多語言一樣是在編譯期間執行。也就是說,import可以出現在任何地方,只有執行到這個import行時,才會執行導入操作。且在import某個模塊之前,無法訪問這個模塊的屬性。
python在import導入模塊時,首先搜索模塊的路徑,然后編譯并執行這個模塊文件。雖然概括起來只有兩個過程,但實際上很復雜。
前文已經解釋了import的模塊搜索過程,所以這里大概介紹import的其它細節。
以前面的a.py中導入模塊文件b.py為例:
importb
import導入模塊時,搜索到模塊文件b.py后:
1.首先在內存中為每個待導入的模塊構建module類的實例:模塊對象。這個模塊對象目前是空對象,這個對象的名稱為全局變量b。
注意細節:module類的對象,變量b。
輸出下它們就知道:
print(b)
print(type(b))
輸出結果:
因為b是全局變量,所以當前程序文件a.py中不能重新對全局變量b進行賦值,這會使導入的模塊b被丟棄。例如,下面是錯誤的:
importb
b=3
print(b.x)#已經沒有模塊b了
另外,因為import導入時是將模塊對象賦值給模塊變量,所以模塊變量名不能是python中的一些關鍵字,比如if、for等,這時會報錯。雖然模塊文件名可以為list、keys等這樣的內置函數名,但這會導致這些內置函數不可用,因為根據變量查找的作用域規則,首先查找全局變量,再查找內置作用域。也就是說,模塊文件的文件名不能是這些關鍵字、也不應該是這些內置函數名。
File"g:/pycode/new.py",line11
importif
^
SyntaxError:invalidsyntax
2.構造空模塊實例后,將編譯、執行模塊文件b.py,并按照一定的規則將一些結果放進這個模塊對象中。
注意細節,編譯、執行b.py、將結果保存到模塊對象中。
模塊第一次被導入的時候,會進行編譯,并生成.pyc字節碼文件,然后python執行這個pyc文件。當模塊被再次導入時,如果檢查到pyc文件的存在,且和源代碼文件的上一次修改時間戳mtime完全對應(也就是說,編譯后源代碼沒有進行過修改),則直接裝載這個pyc文件并執行,不會再進行額外的編譯過程。當然,如果修改過源代碼,將會重新編譯得到新的pyc文件。
注意,并非所有的py文件都會生成編譯得到的pyc文件,對于那些只執行一次的程序文件,會將內存中的編譯結果在執行完成后直接丟棄(多數時候如此,但仍有例外,比如使用compileall模塊可以強制編譯成pyc文件),但模塊會將內存中的編譯結果持久化到pyc文件中。另外,運行字節碼pyc文件并不會比直接運行py文件更快,執行它也一樣是一行行地解釋、執行,唯一快的地方在于導入裝載的時候無需重新編譯而已。
執行模塊文件(已完成編譯)的時候,按照一般的執行流程執行:一行一行地、以代碼塊為單元執行。一般地,模塊文件中只用來聲明變量、函數等屬性,以便提供給導入它的模塊使用,而不應該有其他任何操作性的行為,比如print()操作不應該出現在模塊文件中,但這并非強制。
總之,執行完模塊文件后,這個模塊文件將有一個自己的全局名稱空間,在此模塊文件中定義的變量、函數等屬性,都會記錄在此名稱空間中。
最后,模塊的這些屬性都會保存到模塊對象中。由于這個模塊對象賦值給了模塊變量b,所以通過變量b可以訪問到這個對象中的屬性(比如變量、函數等),也就是模塊文件內定義的全局屬性。
只導入一次
假設a.py中導入了模塊b和模塊sys,在b.py中也導入了模塊sys,但python默認對某個模塊只會導入一次,如果a.py中先導入sys,再導入b,那么導入b并執行b.py的時候,會發現sys已經導入了,不會再去導入sys。
實際上,python執行程序的時候,會將所有已經導入的模塊放進sys.module屬性中,這是一個dict,可以通過下面的方式查看已導入的模塊名:
>>>importsys
>>>list(sys.module.keys())
如果某個程序文件中多次使用import(或from)導入同一個模塊,雖然不會報錯,但實際上還是直接使用內存中已裝載好的模塊對象。
例如,b.py中x=3,導入它之后修改該值,然后再次導入,發現b.x并不會發生改變:
importb
print(b.x)#3
b.x=33
print(b.x)#33
importb
print(b.x)#33
但是python提供了reload進行多次重復導入的方法,見后文。
使用別名
import導入時,可以使用as關鍵字指定一個別名作為模塊對象的變量,例如:
importbasbb
bb.x=3
print(bb.x)
這時候模塊對象將賦值給變量bb,而不是b,b此時不再是模塊對象變量,而僅僅只是模塊名。使用別名并不會影響性能,因為它僅僅只是一個賦值過程,只不過是從原來的賦值對象變量b變為變量bb而已。
以上內容為大家介紹了Python導入模塊時的過程,希望對大家有所幫助,如果想要了解更多Python相關知識,請關注IT培訓機構:千鋒教育。