一、模塊導入方法python
常見的場景:mysql
一個模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的後綴,導入模塊能夠實現功能的重複利用sql
import加載的模塊分爲四個通用類別: shell
1 使用python編寫的代碼(.py文件)oracle
2 已被編譯爲共享庫或DLL的C或C++擴展app
3 包好一組模塊的包ide
4 使用C編寫並連接到python解釋器的內置模塊函數
a. import語句測試
python 內置了不少模塊,好比os、sys、time等,也能夠是自定義模塊、模塊包、C擴展等,使用import沒法區分導入的模塊類型優化
import 模塊名
例如:導入spam.py
import spam(不含.py)
導入多個模塊:
import os,time,sys
模塊能夠包含可執行的語句和函數的定義,這些語句的目的是初始化模塊,它們只在模塊名第一次遇到導入import語句時才執行(import語句是能夠在程序中的任意位置使用的,且針對同一個模塊import不少次,爲了防止你重複導入,python的優化手段是:第一次導入後就將模塊名加載到內存了,後續的import語句僅是對已經加載大內存中的模塊對象增長了一次引用,不會從新執行模塊內的語句)
每一個模塊都是一個獨立的名稱空間,定義在這個模塊中的函數,把這個模塊的名稱空間當作全局名稱空間,這樣咱們在編寫本身的模塊時,就不用擔憂咱們定義在本身模塊中全局變量會在被導入時,與使用者的全局變量衝突
導入模塊幹了哪些事:
1 執行源文件
2 以一個源文件的全局名稱空間
3 在當前位置拿到一個模塊名,指向2建立的名稱空間
#測試一:money與spam.money不衝突 #test.py import spam money=10 print(spam.money) 輸出: from the spam.py 1000 #測試二:read1與spam.read1不衝突 #test.py import spam def read1(): print('========') spam.read1() 輸出: from the spam.py spam->read1->money1000 #測試三:執行spam.change()操做的全局變量money仍然是spam中的 #test.py import spam money=1 spam.change() print(money) 輸出: from the spam.py 1
模塊別名功能
練習:
有兩鍾sql模塊mysql和oracle,根據用戶的輸入,選擇不一樣的sql功能
#mysql.py def sqlparse(): print('from mysql sqlparse') #oracle.py def sqlparse(): print('from oracle sqlparse') #test.py db_type=input('>>: ') if db_type == 'mysql': import mysql as db elif db_type == 'oracle': import oracle as db db.sqlparse()
爲已經導入的模塊起別名的方式對編寫可擴展的代碼頗有用,假設有兩個模塊xmlreader.py和csvreader.py,它們都定義了函數read_data(filename):用來從文件中讀取一些數據,但採用不一樣的輸入格式。能夠編寫代碼來選擇性地挑選讀取模塊
if file_format == 'xml': import xmlreader asreader elif file_format == 'csv': import csvreader asreader data=reader.read_date(filename)
b. from…import語句
from 模塊名 import 模塊名中的方法
例如:from spamimport money,read1,read2,change
若是模塊中的方法太多,能夠使用:
from spam import * (不推薦使用,容易與執行文件的命名空間衝突)
__all__=['money','x'] #對from spam import * 有用,以後導入money、x方法
_money=1000 #對from spam import * 有用,不會導入這個方法
對比import spam,會將源文件的名稱空間'spam'帶到當前名稱空間中,使用時必須是spam.名字的方式,而from 語句至關於import,也會建立新的名稱空間,可是將spam中的名字直接導入到當前的名稱空間中,在當前名稱空間中,直接使用名字就能夠了
#spam.py print('from the spam.py') money=0 def read1(): print('spam->read1->money',money) def read2(): print('spam->read2 calling read') read1() def change(): global money money=0 # 執行文件 from spam import money,read1,read2,change money=0 print(money) print(read1) 輸出: from the spam.py #首先執行spam.py 0 #仍然是當前執行文件的命名空間中的money <function read1 at 0x00000000026DE950>
優勢:使用源文件內的名字時無需加前綴,使用方便
缺點:容易與當前文件的名稱空間內的名字混淆
c. 模塊搜索路徑
模塊只在第一次導入時纔會執行,以後的導入都是直接引用內存已經存在的結果
import sys
print('spam' in sys.modules) #存放的是已經加載到內的模塊
注意:自定義的模塊名必定不要與python自帶的模塊名重名
模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊
import time import importlib import spam #導入模塊會把硬盤中的模塊內容加載到內存中 time.sleep(20) import spam #再次導入會直接從內存中查找,忽略硬盤中模塊內容 print(spam.money) importlib.reload(spam) #會從新加載模塊(只在測試環境使用) print(spam.money)
import sys
print(sys.path) #模塊的搜索路徑
sys.path從如下位置初始化
1 執行文件所在的當前目錄
2 PTYHONPATH(包含一系列目錄名,與shell變量PATH語法同樣)
3 依賴安裝時默認指定的
加入模塊路徑:
import sys print(sys.path) sys.path.insert(0,r'要添加的模塊路徑') #插入模塊路徑 sys.path.append(r'要添加的模塊路徑') #追加模塊路徑
d. 區分python文件的兩種用途
文件當作腳本(執行文件)運行時__name__等於__main__
文件當作模塊被加載運行時__name__等於模塊名
# m1.py import os,sys x=1 def func1(): print('from m1') def func2(): print('from m2') def func3(): print('from m3') # print(__name__) #文件當作腳本運行時__name__等於__main__ #文件當作模塊被加載運行時__name__等於模塊名 if __name__ == '__main__': #當作腳本使用時才執行 func1() func2() func3() # run.py import m1 #導入m1模塊 m1.func3()
e. 包
python3中建立文件夾會自動建立__init__.py
python2中建立包須要手動建立__init__.py
1. 不管是import形式仍是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提升警覺:這是關於包纔有的導入語法
2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)
3. import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字一樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件
強調:
1. 在python3中,即便包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下必定要有該文件,不然import 包報錯
2. 建立包的目的不是爲了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊
3.凡是在導入時帶點的,點的左邊都必須是一個包