模塊和包,from 、import 的底層到底干了啥
模塊
函式,是對某些功能的封裝,而模塊是將特定函式、類、物件等封裝成形式為一個獨立的 .py檔案,是為了更合理的規范代碼,維護代碼,同型別的功能封裝在一起,即簡單清晰,更重要的是能避免命名沖突,
包
模塊的出現方便了代碼的組織管理,但是還存在像模塊名沖突,模塊雜亂,功能劃分不具體等問題!為了解決這些問題,合理的管理Python的各種模塊,引入了包管理的機制,即一個帶有__init__.py檔案的檔案夾就稱為一個包,包通過目錄來組織模塊,包可以包含包,包含模塊,表現形式就是特殊的檔案夾!
包的分類
內建的包
urllib、multiprocessing、json等第三方包
Django、flask、numpy、Pilow等用戶自定義包
就是我們自己寫的 帶有 __init__.py的目錄了
包和模塊的用法和注意事項
關于命名
包名和模塊名盡量避免中文出現
包名和模塊名盡量的避免和Python的內置模塊名和包名沖突,尤其是包名
包和模塊的命名,遵循Python變數命名規范
安裝
# 類UNIX/Linux/OSX
# 語法 pip3 install 包名==版本號 如果不確定具體的版本號 可用 ~= 代替 ==
pip3 install django~=2.0 # 安裝最靠近2.0版本的django
pip3 install pymysql==0.93 # 安裝 0.93 版本的 pymysql
# windows 和 Linux 沒太大差別
通常我們會帶上一些常用引數,或直接修改配置來指定pip的行為
換pypi源
# 使用 -i 引數
pip install numpy -i https://mirrors.aliyun.com/pypi/simple/
從requirements.txt安裝
# 使用 -r 引數 requirements.txt 檔案必須在當前目錄下
pip install -r requirements.txt
本地安裝
pip install setup.py
從git安裝
# pip install git+git:倉庫地址
pip install git+git://github.com/blackmonkey121/verify.git
包的匯入
先看官方檔案
sys.modules
This is a dictionary that maps module names to modules which have already been loaded. This can bemanipulated to force reloading of modules and other tricks. However, replacing the dictionary will notnecessarily work as expected and deleting essential items from the dictionary may cause Python to fail.
sys.path
A list of strings that specifies the search path for modules. Initialized from the environment variablePYTHONPATH, plus an installation-dependent default.As initialized upon program startup, the first item of this list, path[0], is the directory containingthe script that was used to invoke the Python interpreter. If the script directory is not available (e.g.if the interpreter is invoked interactively or if the script is read from standard input), path[0] is theempty string, which directs Python to search modules in the current directory first. Notice that the scriptdirectory is inserted before the entries inserted as a result of PYTHONPATH.A program is free to modify this list for its own purposes. Only strings and bytes should be added to sys.path; all other data types are ignored during import.See also Module site This describes how to use .pth files to extend sys.path.
sys.modules行為
sys.modules中保存的是記憶體中已加載的模塊名和模塊地址的映射關系,它是一個字典,字典的鍵就是模塊名 (str)字典的值是模塊物件(確切的說是它的參考)
sys.path行為
指定模塊搜索路徑的字串串列,從環境變數初始化python.path的初始值,加上默認的安裝位置,
import sys
for path in sys.path:
print(path)
# /Users/ms # 腳本所在的位置
# /Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip
# /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6
# /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload
# /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
它在程式啟動時初始化,此串列的第一項sys.path[0]就是腳本檔案所在的位置(當前位置),
如果腳本目錄不可用(例如如果以互動方式呼叫解釋器或從標準輸入讀取腳本,則sys.path[0]是空字串,指示python首先搜索當前目錄中的模塊,
程式可以為自己的目的自由修改這個串列,只應將字串和位元組添加到sys.path;匯入期間忽略所有其他資料型別,
from ... import ...
你似乎很熟悉他們,但他們的行為細節可能你知道的不足夠,在這之前你要做好準備,他可能有些不太好理解,
from 做了啥
# 以這句話為例
from PIL.image import getmodetype
1 解釋器遇到from,首先去sys.modules.keys()搜索模塊名PIL,匹配不上就去sys.path的每一個路徑下匹配模塊名PIL,
2 匹配上,就在sys.modules添加一個新的映射{‘PIL’:PIL <module 'PIL' from '/Users/ms/Virtual/test.env/lib/python3.6/site-packages/PIL/init.py'>},然后去執行包下的__init__.py檔案(如果__init__.py檔案中存在from 則繼續遞回的執行),此時會將當前目錄下的子模塊全部加載到該包的命名空間中,
3 如果后面還有. 就到PIL下查找image ,一直重復下去直到遇見 import 關鍵字 停止from
4 此時from 的作業已經完成,
tips : 在任意一步中沒法找到包或模塊都會報錯,來終止程式,
import 做了啥
# 以此為例
import PIL
1 解釋器拿到import后,首先去sys.modules.keys()搜索模塊名,匹配不上就去sys.path的每一個路徑下匹配PIL,如果匹配上,就在sys.modules創建一個新的映射, 到此時與 from 的作用是一致的,
2 然后Python會在內部創建這個物件(開辟空間),然后在這個空間決議這個物件(這也叫命名空間,就是匯入模塊時創建那個全域變數了),也就是在這個空間執行PIL,也正因如此,import 后的物件我們可以直接使用,而from 不行,
3 如果import后面跟的是個包,則會執行__init__.py,如果是模塊,則會直接執行該模塊,
tips:
如果在 import 程序中遇見 from或import 都會按照他們各自的行為去執行,
from ... import ...
使用from陳述句可以將模塊或包遞回的添加到 sys.modules,注意并沒有執行代碼,僅僅是執行了包下的__init__.py檔案,
# 以此為例
from matplotlib import pyplot as plt
from 會找尋 sys.modules 中是否存在 matplotlib,如果沒找到,將會按照 sys.path 中的路徑去逐個遍歷尋找 matplotlib,(sys.path 的第一項總是當前目錄,也就是說如果我們在當前目錄下有一個檔案叫matplotlib.py或者某個包叫 matplotlib,那將不會使用我們安裝的 第三方matplotlib 因此 檔案命名要注意這個問題,)
一旦找到,將不會往下尋找,直接將找到的模塊或包__init__.py 添加到sys.modules中,同時將所有的子模塊都添加到該包的命名空間中,如果所有sys.path的目錄下都沒有找到將會報錯,
遇見import后該包的命名空間中尋找pyplot是否存在,不存在則報錯,存在將pyplot物件加載到當前腳本的命名空間,并在此處執行pyplot, 如果 匯入陳述句屬于全域,那么該包也會屬于全域,反之,則屬于區域,
__init__ 和 __all__
關于__init__.py
在 __init__.py 中可以像正常的Python檔案那樣寫一些代碼,這些會在每次匯入時被默認的執行,通常不建議在 該檔案下撰寫代碼,
__all__ 通常會被推薦寫在 __init__.py 中,它能控制包的匯入行為, 當使用模糊匯入時,如果__init__.py 檔案為空,將不會匯入任何模塊,如果__init__.py寫了 __all__ 則只會匯入 __all__ 包含的物件,
__all__ 是一個串列,串列物件應該是字串,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/122696.html
標籤:Python
上一篇:Python 快取
下一篇:python 命名空間和作用域
