再看一下os識別符號的型別及os指向的這個物件。
print(type(os))
print(type(os.path))
print(global()["os"]) # 收集全域性變數,檢視os物件資訊-----輸出結果-----
上面結果顯示os和os.path是乙個module型別,這也是os可以使用import匯入的原因。只有module型別才能被匯入。同理os.path也可以直接被匯入。
print(dir())importos.pathprint(dir())-----輸出結果-----#省略
匯入前:全域性變數中沒有"os" 或者 "os.path"匯入後:出現了"os",但是沒有"os.path"
os.path並不是乙個合法的識別符號(字元,下劃線,數字),所以這個os.path物件沒有被變數接受,但是我們之後需要能訪問這個os.path物件 ,所以python為我們保留了os變數指向os模組。我們才可以使用os.path的方式訪問。當然我們使用別名的方式os.path就可以被接收了。
importos.path as osp
osp.dirname(".") #osp 即指向 os.path模組物件.呼叫它全域性空間中的dirname(".")函式
print(type(osp)) #
print(globals()["osp"]) #
osp直接指向了我們需要os.path模組,我們可以osp進行訪問,os變數也就沒有意義,所以此時的全域性變數總並不存在os這個全域性變數,但是os這個模組確實被import載入到記憶體空間中。只是在該模組中沒有對應的表示符進行對應。
模組搜尋順序
在sys.path中記錄了模組的所有順序,並且可以程式執行時候,匯入了哪些類,所有被匯入的類都會快取在sys.modules中,呼叫即可檢視。
importsysprint(*sys.path, "\n", *sys.modules, sep="\n")--------輸出結果------
'''d:\學習\練習\myproject # 當前路徑
d:\學習\練習 # pycharm 建立的專案環境
e:\python\python36.zip # 以下為python安裝路徑下的各個路徑,可以為zip,egg檔案
e:\python\dlls
e:\python\lib
e:\python
e:\python\lib\site-packages'''
.egg檔案是由setuptools庫建立的包,第三方庫常用的格式,新增了元資料資訊的zip檔案。
使用from匯入
from ... import ...從乙個模組中匯入物件,這個模組可能是乙個.py檔案也可能是乙個包(目錄),匯入的物件可以是包或者模組下的函式,類,模組等全域性變數識別符號,並且匯入後可以直接使用import後的原變數識別符號進行訪問,而不需要加上模組字首。from 和import後指定的內容都將被載入到記憶體。
from os import path #從os 匯入 path模組,並可以使用path全域性變數直接訪問
from os.path import dirname #從os.path 模組匯入 dirname方法,可以直接通過dirname識別符號訪問該方法物件。
from os.path import * #預設從os.path模組匯入所有公共變數(非下劃線開頭),並直接使用原變數名作為該包下的全域性變數
使用第三種方式容易造成該包中的全域性變數被匯入包中全域性變數覆蓋。除非清楚的知道兩個包中的變數不會重名,否則盡量不使用。
使用 from ... import *預設匯入的是公開變數(非_或__打頭的變數),非公開變數匯入必須手動才能訪問,或者新增到__all__屬性中才能使用*匯入
from os import _abc, __abc #直接指定可匯入,* 預設不含該類屬性
__all__
在被匯入模組中,可以新增__all__屬性來指定該模組預設的全部可向外匯出的模組。配合from ...import * 使用。__all__屬性是乙個字串列表,這些字串必須與該全域性空間中的全域性變數名對應,或者與該包下的子包名對應。
__all__ = ["x", "y", "_z"]
x= 1y= 2z= 3_z= 4
這個包被其他包使用 *匯入時,匯出__all__中對應的x, y,_z變數,實現了我們手動控制變數的匯出。
包匯入時屬性優先,沒有這個屬性才會判斷是否有這個模組。所以如果屬性名和模組名衝突,該模組將無法再被匯出。
包python中的包就是乙個資料夾,資料夾下放各個模組的.py檔案或者乙個子包,方便管理。在包上也是可以寫**,這就是需要這個包下的__init__.py檔案,這個檔案屬於這個包,當我們僅僅匯入乙個包時候,就是匯入這個包下的__init__.py檔案中的全域性變數所指定的內容。並不會自動的匯入這個包下的子模組。
包檔案和模組檔案
包模組的**託管到包下的__init__.py檔案中,即使包沒有__init__檔案仍然可以被匯入,但並沒有匯入任何內容,這種情況下只能通過這個包名去尋找這個包下的模組檔案。使用from ... inport ...匯入子模組中的內容。
包是乙個稍微特殊的模組物件,包的屬性有['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__'],根據__package__屬性可以判斷它是否是乙個包,該屬性為none或者不存在表示不是包。
包下的模組為這個包的子模組,他們之間可以通過package.mod_name進行訪問,前提是這個模組已經被匯入,可以使用from package import mol_name或者import package.mol_name進行匯入,兩種匯入效果相同,只是匯入空間的變數名不同,使用形式不同。但是只import package無法自動匯入它的子包,package.mul_name將不能訪問。
相對匯入和絕對匯入
使用import匯入模組順序在sys.module記錄,預設優先從執行檔案的當前目錄中尋找,無法找到再去python安裝檔案中的庫中尋找。這是一種絕對路徑匯入。
相對匯入通常在乙個包中使用,方便的將包中的各個模組進行關聯,這種關聯只受包內檔案的相對位置約束,然而對於乙個包我們通常不會去干涉內部的檔案關係。相對匯入原則遵循檔案系統使用原則,即使是包__init__.py檔案,這時屬於這個包下的乙個子檔案,等同於這個包下的其他子檔案。
符號示例
.m當前資料夾中的m模組
..m上一級檔案中的m模組
…m上上一級檔案中的m模組
from .m import a #將會在當前目錄下找 m 檔案並匯入a
from ..m import a #訪問該檔案的上一層目錄找 m 檔案並匯入a
from .m.m1 import a #當前檔案所在目錄中的m包下的 m1檔案並匯入a
以上匯入方式只能在包中使用,(任何乙個相對匯入的路徑不能涉及主包所處的當前目錄)這些檔案不能作為主模組直接執行,它是一種包內部的關係的建立方式,直接執行將報錯。
命名空間
當我們匯入乙個模組時,我們可以訪問這個模組是因為在當前的作用域內部,建立了乙個與模組名同名的全域性變數,才可以通過這個全域性變數對這個模組進行訪問。所以我們是否能使用乙個模組,需要兩個條件:
1、該模組被載入到記憶體中
2、可以找到乙個識別符號直接和這個模組物件關聯或者可以通過其他識別符號的成員訪問方式訪問到這個模組物件。
不同的匯入檔案方式在這個命名空間中建立的識別符號是不同的
import os #只匯入os模組(os下的__init__.py中的內容),建立os識別符號
import os as o #只匯入os模組,建立o識別符號
import os.path #同時匯入os 和 os.path,只建立 os識別符號,指向os模組。os.path可訪問
import os.path as osp #同時匯入os 和 os.path,只建立 osp識別符號,指向os.path模組,os模組在記憶體,但是無法訪問,無識別符號
from os import path #同時匯入os 和 os.path,只建立path識別符號,指向os.path。os無法訪問,無識別符號
from os import * #同時匯入os中所有公開變數,如果有__all__屬性,匯入指定的內容,建立所有 * 指代的識別符號,不會建立os
form .mimport a #在包內匯入, m 和 a 均匯入,m識別符號可能存在,可使用 dir檢視確認再使用,a 識別符號存在
自定義模組
模組命名規範:
在匯入模組時,會使用模組名作為識別符號,這就要求模組名滿足識別符號的命名規範,這樣才可以被匯入。並且模組一幫使用小寫字元,可以使用下劃線分割。
模組重複匯入
模組被載入一次後會在記憶體中快取這個模組物件,這個模組的辨識資訊被快取到sys.modules中。匯入模組時候,首先是從sys.modules中查詢該模組是否已經被載入,如果已存在,並不會從檔案中讀取,而是直接使用記憶體中已存在的這個模組物件,否則import會io搜尋該模組的檔案,編譯,執行這個模組並載入大記憶體。
快取的模組被儲存在sys.module中,包括自己,其中還包括直譯器執行需要的模組。
自定義模組a/b/c路徑,如果只匯入a模組import a,直接使用a.b是有風險的,該模組沒有被載入,只有使用import關鍵字時,直譯器才會模組進行載入,而不會自動的載入。
模組執行
當我們執行乙個.py檔案,此時直譯器會啟動去執行,但在執行這個檔案之前,直譯器還需要其他的工作,比如匯入一些包,例如io,將我們的.py檔案讀入記憶體,或者build-in,因為我們可能使用到了這個內建函式。還有其他很多準備流程,當這個工作完成後,才會執行我們自己的.py檔案。而這個.py檔案也會被命名為__main__包。檢視這個模組名,顯示為__main__
print(__name__) #__main__
除直譯器執行的**外,這個模組將會作為最外層的**塊,這個模組的結束代表該執行緒的結束。也被稱作頂層**。頂層**包的"name"屬性為__main__,其餘模組的__name__屬性為模組名。所以測試**通常這樣寫
if __name__ == "__main__":#test code
只有這個模組直接執行時,if 中的測試**才會執行。
python 模組和包 python模組和包
一.模組 python 模組 module 是乙個 python 檔案,以 py 結尾,包含了 python 物件定義和python語句。模組能定義函式,類和變數,模組裡也能包含可執行的 二.匯入模組 1.語法 import模組名from 模組名 import功能名from 模組名 import i...
Python 模組和包
包 模組的一種組織結構 乙個包由多個模組構成,即包含多個.py檔案 1匯入包的幾種形式 1 import module 將module模組中屬性列表的所有屬性匯入執行環境,使用時需要新增模組名稱,例如 module.func 2 from module import attrname,fucnnam...
python 模組和包
1.內建模組 本身就帶有的庫,就叫做python的內建的庫。模組 庫 一些常見的內建模組 os 和作業系統相關 os.path sys 和系統相關 sys.path re 正規表示式 2.第三方模組 非python本身自帶的庫,就是所謂的第三方的庫 3.模組的匯入 import as yy from...