python載入模組 Python 模組的載入順序

2021-10-11 00:03:39 字數 4153 閱讀 4248

基本概念

module

模組, 乙個 py 檔案或以其他檔案形式存在的可被匯入的就是乙個模組

package

包,包含有 init 檔案的資料夾

relative path

相對路徑,相對於某個目錄的路徑

absolute path

絕對路徑,全路徑

python 直譯器是如何查詢包和模組的

python 執行乙個 py 檔案,無論執行的方式是用絕對路徑還是相對路徑,interpreter 都會把檔案所在的 directory 加入 sys.path 這個 list 中,並且是索引為 0 的位置。python 就是在 sys.path 中查詢包和模組的。

# test.py

# coding:utf-8

import sys

print(sys.path)

print('now in main.py')

def hello():

print('michael hello')

if __name__ == '__main__':

hello()

# 執行 python test.py

$ python test.py

now in test.py

michael hello

python 直譯器查詢包的順序

直譯器查詢包:

直譯器會預設載入一些 modules,除了sys.builtin_module_names 列出的內建模組之外,還會載入其他一些標準庫,都存放在sys.modules字典中。

然後就是搜尋 sys.path 路徑下的模組了。

in [3]: import sys

in [4]: print(sys.builtin_module_names)

('_abc', '_ast', '_codecs', '_collections', '_functools', '_imp', '_io', '_locale', '_operator', '_signal', '_sre', '_stat', '_string', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'atexit', 'builtins', 'errno', 'faulthandler', 'gc', 'itertools', 'marshal', 'posix', 'pwd', 'sys', 'time', 'xxsubtype', 'zipimport')

這樣的查詢順序將會導致同名包或模組被遮蔽。

示例2:

# tree

$ tree . -l 1

├── __init__.py

├── name

├── os.py

├── test2.py

├── test.py

└── test.pyc

# test2.py

import os

from redis import redis

from test import hello

print('now in test2.py')

print(os.getcwd())

# 執行 python test2.py

$ python test2.py

traceback (most recent call last):

file "test2.py", line 2, in

from redis import redis

importerror: no module named redis

這裡的 os 模組並不是是 built-in module,上面已經將 sys.builtin_module_names 內容列印出來了。只是 python 直譯器啟動時就載入到了 sys.modules中快取起來了。所以,即使在同目錄下有同名模組,直譯器依然是可以找到正確的 os 模組的!如果你在import os之前,先執行del sys.modules['os'],那麼,標準模組 os 就會被同目錄下的 os.py 遮蔽了。

redis 屬於第三方模組,預設安裝位置是 python 環境變數中的 site-packages,直譯器啟動之後,會將此目錄加到 sys.path,由於當前目錄會在 sys.path 的首位,當前目錄的 redis 優先被找到了,site-packages 中的 redis 模組被遮蔽了。

綜上所述,搜尋的乙個順序是:sys.modules 快取 -> sys.path[0] 即當前目錄查詢 -> sys.path[1:]路徑查詢。

同時發現,模組被載入的時候,其中非函式或類的語句,例如 print('hello')、name=michael等,是會在 import的時候,預設就執行了。

互動式執行環境的查詢順序

互動執行環境,直譯器會自動把當前目錄加入到sys.path,這一點和直接執行檔案是一樣的,但是這種方式下,sys.path[0] 是儲存的當前目錄的相對路徑,而不是絕對路徑。

in [4]: import sys

in [5]: sys.path[0]

out[5]: ''

模組中的 __file__ 變數

檔案中的 __file__

當模組以檔案的形式出現 file 指的是模組檔案的路徑名,以相對路徑執行 file 是相對路徑,以絕對路徑執行 file 是絕對路徑:

# test3.py

print __file__

# 執行 python test.py

$ python test3.py

test3.py

互動式 shell 中的 __file__

前互動式 shell 的執行並不是以檔案的形式載入,所以不存在 __file__ 這樣的屬性:

in [8]: __file__

nameerror traceback (most recent call last)

in ()

----> 1 __file__

nameerror: name '__file__' is not defined

sys.ar**[0] 變數

sys.ar**[0] 是獲得入口執行檔案路徑,__file__ 是真實被執行模組的檔案路徑。比如下面例子中,test2.py 就是入口執行檔案,而 test.py 就是在 import 時真實被執行的模組

# test.py

print(__file__)

print(sys.ar**[0])

# test2.py

import test

# 執行 python test2.py

test2.py # sys.ar**[0]

sys.modules 的作用

載入的模組存放在何處? 答案是 sys.modules。 模組一經載入, python 會把這個模組加入 sys.modules 中供下次載入使用,這樣可以加速模組引入,起到快取作用。sys.modules 是乙個 dict 型別的值。

in [14]: sys.modules['requests']

keyerror traceback (most recent call last)

in ()

----> 1 sys.modules['requests']

keyerror: 'requests'

in [15]: import requests

in [16]: sys.modules['requests']

out[16]:

# 沒有預先引入 math,但是 sys.modules 中已經有這個鍵

in [18]: sys.modules['math']

out[18]:

需要注意的是, sys.modules['math'] 儘管可以看到 math 鍵,但是,要使用它,還是需要顯示 import math 之後才能使用的,因為那只是 python 直譯器後台快取的,你不顯示引入,本地空間還是不會去發現它。

總結python 通過查詢 sys.path 來決定包的匯入,python直譯器啟動時載入的模組快取 > 同級目錄 > sys.path[1:]。python 中的特有屬性 __file__ 以及 sys.ar**[0]、sys.ar**[0]、sys.modules 可以幫助分析包的查詢和匯入過程。

解決這個問題,請教了大牛同事,果然一下子讓我明白了。於是,自問自答了在 segmentfault 上提的問題:

參考

python 模組載入

本文主要介紹python模組載入的過程。所有的module都是由物件和物件之間的關係組成。python中所有的東西都是物件,分為三類 型別type 類class和例項instance。三種物件之間的兩種關係 類和物件的關係可以通過內建方法type來辨別。python中,任何乙個類都是直接或間接繼承自...

python模組載入

秉著python一切皆為物件的原則,我來看看python庫的型別 import os print type os 結果為乙個名為 module 的型別 1 什麼樣的檔案型別叫做模組 以.py檔案結尾的都可以被python認為是模組 2 package的概念 為了幫助組織模組並提供名稱層次結構,pyt...

python 模組的載入

不管是用import還是用from mmmm import 的方式匯入模組,當程式執行之後,回頭在看那個儲存著mmmm.py檔案的目錄中,多了乙個檔案 ls mmm mmmm.py mmmm.pyc 在這個目錄下面,除了原來的那個mmmm.py之外,又多了乙個mmmm.pyc檔案,這個檔案不是我寫的...