Python基礎(chǔ)38-包/模塊(導入及其底層邏輯)

1 導入模塊后具體做了什么?
2 從哪個位置找到需要導入的模塊
3 導入模塊的常見場景晴竞?

1 導入模塊后具體做了什么亲族?

1.1 第一次導入

  1. 在自己當下的命名空間中,執(zhí)行所有代碼
  2. 創(chuàng)建一個模塊對象拂蝎,并將模塊內(nèi)所有頂級變量以屬性的形式綁定在模塊對象上
  3. 在 import 的位置穴墅,引入 import 后面的變量名稱到當前命名空間

1.1.1 在自己當下的命名空間中,執(zhí)行所有代碼

Test2.py

name = "Test2"
age = 2

print("執(zhí)行了Test2所有代碼")
Test1.py

import Test2


# 讓后 run 該分代碼
>>>>打印結(jié)果
執(zhí)行了Test2所有代碼
  • 也就是說 Test1.py 中導入了 Test2模塊后温自,在運行 Test1模塊代碼時玄货,會先讓 Test2中的代碼在 Test2 的自己的命名空間中執(zhí)行 Test2的所有代碼
  • 其實,從使用角度來理解的話悼泌,當然是 Test2 內(nèi)的代碼先跑完松捉,Test1 中才能使用 Test2 中的變量等資源啊。

1.1.2 創(chuàng)建一個模塊對象馆里,并將模塊內(nèi)所有頂級變量以屬性的形式綁定在模塊對象上

(具有內(nèi)存地址及類型)

Test2.py

name = "Test2"
age = 2

print("執(zhí)行了Test2所有代碼")
Test1.py

import Test2

# 查看Test2
print(Test2)

# 查看內(nèi)存地址
print(id(Test2))

# 查看類型
print(type(Test2))

# 通過打印 Test2 對象的屬性隘世,驗證在 Test1 中需要通過 模塊名.屬性形式訪問的原因
print(Test2.__dict__)


>>>>打印結(jié)果
執(zhí)行了Test2所有代碼
<module 'Test2' from '/Users/xxx/Desktop/PythonProject/PackageAndModule/Test2.py'>
4560942648
<class 'module'>
# __dict__ 字典打印結(jié)果沒有天上自己試驗

1.1.3 在 import 的位置,引入 import 后面的變量名稱到當前命名空間

  • 在 Test1 中通過 Test2變量名來使用 Test2 模塊的資源
Test2.py

name = "Test2"
age = 2

print("執(zhí)行了Test2所有代碼")
Test1.py

import Test2


print(Test2.name)
print(Test2.age)

>>>>打印結(jié)果
執(zhí)行了Test2所有代碼
Test2
2
  • 將 Test2 這個指向 Test2 模塊的對象變量名引入 當前 命名空間中(注意命名空間即作用域的區(qū)別)
Test1.py


def testFunc():
    import Test2 # 導入到了函數(shù)的命名空間中
    print(Test2.name)

testFunc()

print(Test2.name) # 全局命名空間不能使用 Test2

>>>>打印結(jié)果
Traceback (most recent call last):
執(zhí)行了Test2所有代碼
  File "/Users/xxx/Desktop/PythonProject/PackageAndModule/Test1.py", line 14, in <module>
Test2
    print(Test2.name)
NameError: name 'Test2' is not defined

1.2 第二次導入

1.2.1直接執(zhí)行1.1.3這個步驟

Test2.py

name = "Test2"
age = 2

print("執(zhí)行了Test2所有代碼")
Test1.py

import Test2


print(Test2.name)
print(Test2.age)

# 再次導入鸠踪, 打印中并沒有出現(xiàn)兩次“執(zhí)行了Test2所有代碼”
import Test2

>>>>打印結(jié)果
執(zhí)行了Test2所有代碼
Test2
2

1.3 注意

from ... import ... 導入方式與 import ... 導入方式底層執(zhí)行步驟區(qū)別

  • 兩種導入方式均都會大致的執(zhí)行上述的3個步驟
  • 多次導入模塊丙者,該模塊并不會執(zhí)行多次
  • 兩種導入方式并不存在哪一種更節(jié)省內(nèi)存之說,區(qū)別在于把哪一部分內(nèi)容拿到當前位置來用营密,因為一旦導入都將模塊內(nèi)的對象創(chuàng)建好械媒。
Test2.py

name = "Test2"
age = 2

print("執(zhí)行了Test2所有代碼")
Test1.py

from Test2 import name

print(name)

>>>>打印結(jié)果
執(zhí)行了Test2所有代碼
Test2

2 模塊檢索順序(從哪個位置找到需要導入的模塊)

2.1 第一次導入

  • 按照模塊檢索路徑順序查找

1 內(nèi)建模塊
2 sys.path
2.1 當前目錄環(huán)境變量PYTHONPATH
2.2 Python 安裝路徑
2.3 安裝路徑下的.pth 路徑
2.4 lib 庫 site-packages
2.5 lib 庫 site-packages下的 pth 文件配置
3 其他

2.2.1 第一層級

  • 內(nèi)置模塊<built - in>

2.2.2 第二層級

  1. sys.path
    >>> import sys
    >>> print(sys.path)
    ['', '/usr/local/Cellar/python3/3.6.4_1/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/usr/local/Cellar/python3/3.6.4_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/usr/local/Cellar/python3/3.6.4_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/site-packages']
    >>>
    
  • 構(gòu)成 (如下索引并非指優(yōu)先順序)
    1.1 當前目錄
    1.2 環(huán)境變量 PYTHONPATH 中指定的路徑列表
    1.3 特定路徑下的 .path 文件中的文件路徑列表
    1.4 在 Python 安裝路徑的 lib 庫中搜索
  1. 追加路徑的方式(修改 sys.path 方式)
  • 直接修改 sys.path,只作于本次的執(zhí)行代碼模塊
Test1.py


import sys
sys.path.append("/Users/xxx/Desktop/myTest") 
print(sys.path)

import fkm

# print(fkm.__dict__)
print(fkm.age)

>>>>打印結(jié)果
打印了abc 所有代碼
12

注意該路徑是追加到sys.path最后的评汰,當 工程目錄中有同名模塊時纷捞,會優(yōu)先加載工程內(nèi)的同名模塊

  • 修改環(huán)境變量 PYTHONPATH(自行百度)
    實際,修改PYTHONPATH環(huán)境變量也是修改 sys.path 列表內(nèi)容被去,將環(huán)境變量PYTHONPATH代表的路徑添加到 sys.path中主儡,只不過是默認就給添加了,不同于通過代碼修改编振。
    注意缀辩,系統(tǒng)修改 PYTHONPATH 和 pycharm 添加環(huán)境變量的區(qū)別

  • 添加.pth 文件
    添加 .pth 文件位置可通過 site 模塊查看

    import site
    print(site.getsitepackages())
    
    >>>>打印結(jié)果
    ['/usr/local/Cellar/python3/3.6.4_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages', '/Library/Python/3.6/site-packages']
    

    只需在以上目錄下創(chuàng)建.pth 文件臭埋,然后在文件中添加對應(yīng)模塊路徑即可

2.2 第二次導入

1 從已經(jīng)加載過的模塊中去找

  • 查看已加載模塊
import sys
sys.modules

3 導入模塊的常見場景?

3.1 局部導入

def testFunc():
    import Test2 # 導入到了函數(shù)的命名空間中
    print(Test2.name)

testFunc()

使用的時候才進行導入臀玄,此時 Test2 是一個局部變量瓢阴,只存在于函數(shù)作用域中;減少內(nèi)存的開銷健无;

3.2 覆蓋導入

  • 場景一:
    自定義模塊和非內(nèi)置的標準模塊重名荣恐,根據(jù)前者的存儲位置,有可能前者會覆蓋后者
    建議:自定義模塊命名不要與后者重名

  • 場景二:
    自定義模塊與內(nèi)置模塊重名累贤,內(nèi)置肯定覆蓋自定義
    建議:如果確實需要使用重名的自定義模塊叠穆,可以使用 from ... import ...方式指明絕對路徑進行導入使用

from  package1 import sys
print(sys.name)

3.3 循環(huán)導入

  • 模塊 A 中導入模塊 B, 模塊 B 中又導入模塊 A臼膏;
Test2.py


t2_1 = "t2_1"
t2_2 = "t2_2"

import Test1

print(Test1.t1_1)
print(Test1.t1_2)
Test1.py

t1_1 = "t1_1"
t1_2 = "t1_2"

import Test2

print(Test2.t2_1)
print(Test2.t2_2)

>>>>打印結(jié)果
t2_1
t2_2
t1_1
t1_2
t2_1
t2_2
分析邏輯

3.4 可選導入

  • 兩個功能相近的包硼被,根據(jù)需求優(yōu)先選擇其中一個導入
  • 想優(yōu)先使用 A;當沒有 A 的情況下渗磅,使用 B 作備份
try:
    import Testxxx as t
except ModuleNotFoundError:
    import Test1 as t

print(t.name)

3.5 包內(nèi)導入


明確一下概念

  • 絕對導入和相對導入嚷硫,這兩個概念是相對于包內(nèi)導入而言的

  • 包內(nèi)導入:即是包內(nèi)的模塊導入包內(nèi)的模塊,即package1包內(nèi)的 Test3 內(nèi)導入 Test3_1

  • 包外導入:即是包外的模塊導入包內(nèi)的模塊始鱼,即 Test1 內(nèi)導入package1包內(nèi)的 Test3

  • 查看當前文件參照的執(zhí)行路徑

import sys
sys.path
  • 查看當前模塊名稱

如果文件是直接運行的話仔掸,__name__的值是 __main__
如果是以模塊的形式進行加載文件的話,該名稱的值則是由加載路徑?jīng)Q定医清,格式為:包名.子包名.模塊名 (此時起暮,第一層包名稱作為頂級名稱)
print(__name__)
Test1.py

import package1.Test3

Test3
  • 查找文件順序都是先 內(nèi)置<built-in> 再 sys.path
  • 當點擊運行(使用解析器去執(zhí)行)某一 py 文件時,此時程序會確定當前py 文件所在的目錄会烙,并且將該目錄添加到 sys.path 中负懦,此時的 sys.path內(nèi)容基本確定

3.5.1 概念

3.5.1.1 絕對

  1. 參照sys.path路徑進行檢索
  2. 指明包名或模塊名import afrom a import b
  3. 上述兩點是基于 Python3.x 之后

3.5.1.2 相對

  1. 使用.來指代相對路徑
    .:根據(jù)模塊名(__name__)稱所獲取的當前目錄
    ..:根據(jù)模塊名(__name__)稱所獲取的上層目錄
  2. 如:from . import a持搜、from .. import a

3.5.2 補充

  1. Python3.x 版本之前密似,直接使用 import a。會優(yōu)先從本地當前目錄查找葫盼,并非是 sys.path
  2. 解決方案:from __future__ import absolute_import残腌,使用該代碼語句改變 import 行為

3.5.3 結(jié)論

  • 包內(nèi)導入,使用相對導入
  • 包外導入贫导,使用絕對導入

例子1:Test1 導入 Test3抛猫,Test3 內(nèi)又導入Test3_1;即包外導入+包內(nèi)導入

Test1.py

import package1.Test3
或
from package1 import Test3
Test3.py

from . import Test3_1
不建議寫成   from package1 import Test3_1  孩灯,因為當包名變化時闺金,使用包名的地方都要改動

例子2:多層級導入


Test1.py

print("Test1")
print(__name__)
from package1 import Test3
Test2.py

print("Test2")
print(__name__)

Test3.py

print("Test3")
print(__name__)
from .package_sub1 import Test4
Test3_1.py

print("Test3_1")
print(__name__)
Test4.py

print("Test4")
print(__name__)

from .package_subsub1 import Test5
Test4_1.py

print("Test4_1")
print(__name__)
Test5.py

print("Test5")
print(__name__)

from .. import Test4_1
from ... import Test3_1
# from .... import Test2 #包內(nèi)不能獲取包外的文件

運行 Test1.py

>>>>打印結(jié)果
Test1
__main__
Test3
package1.Test3
Test4
package1.package_sub1.Test4
Test5
package1.package_sub1.package_subsub1.Test5
Test4_1
package1.package_sub1.Test4_1
Test3_1
package1.Test3_1
  • 可以通過上述例子,了解點點的作用
  • 注意:包內(nèi)不能獲取包外的文件
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末峰档,一起剝皮案震驚了整個濱河市败匹,隨后出現(xiàn)的幾起案子寨昙,更是在濱河造成了極大的恐慌,老刑警劉巖掀亩,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舔哪,死亡現(xiàn)場離奇詭異,居然都是意外死亡槽棍,警方通過查閱死者的電腦和手機捉蚤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炼七,“玉大人缆巧,你說我怎么就攤上這事⊥阕荆” “怎么了陕悬?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長姆蘸。 經(jīng)常有香客問我墩莫,道長,這世上最難降的妖魔是什么逞敷? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮灌侣,結(jié)果婚禮上推捐,老公的妹妹穿的比我還像新娘。我一直安慰自己侧啼,他們只是感情好牛柒,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著痊乾,像睡著了一般皮壁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哪审,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天蛾魄,我揣著相機與錄音,去河邊找鬼湿滓。 笑死滴须,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的叽奥。 我是一名探鬼主播扔水,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼朝氓!你這毒婦竟也來了魔市?” 一聲冷哼從身側(cè)響起主届,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎待德,沒想到半個月后君丁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡磅网,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年谈截,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涧偷。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡簸喂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出燎潮,到底是詐尸還是另有隱情喻鳄,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布确封,位于F島的核電站除呵,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏爪喘。R本人自食惡果不足惜颜曾,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秉剑。 院中可真熱鬧泛豪,春花似錦、人聲如沸侦鹏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽略水。三九已至价卤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渊涝,已是汗流浹背慎璧。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留驶赏,地道東北人炸卑。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像煤傍,于是被迫代替她去往敵國和親盖文。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 〇蚯姆、前言 本文共108張圖五续,流量黨請慎重洒敏! 歷時1個半月,我把自己學習Python基礎(chǔ)知識的框架詳細梳理了一遍疙驾。 ...
    Raxxie閱讀 18,918評論 17 410
  • 模塊 一個模塊就是包含了python定義和聲明的文件凶伙,文件名就是模塊名字加上.py后綴,通過導入模塊來引入其他文件...
    斷尾壁虎V閱讀 1,592評論 0 1
  • 用 python 解釋器來編程從 Python 解釋器退出再進入,那么你定義的所有的方法和變量就都消失了它碎。 為此...
    chen_000閱讀 520評論 0 3
  • 很多人都渴望成功函荣,可能有些人卻不知道怎樣成功,成功要什么扳肛。所以有些人的成功就變成了空想傻挂。而我覺得,成功需要是不...
    唯美_4b88閱讀 311評論 0 1
  • 1. 增加snmp v3用戶 # service snmpd stop # net-snmp-config --c...
    SkTj閱讀 1,132評論 0 0