03-Python-包&模組-包和模組的一般操作
學習地址:
1.包/模組的建立
建立模組
直接建立一個.py檔案即可
建立包
建立一個資料夾, 資料夾內務必建立一個__init__.py這個檔案 其實3.3版本往後可以不用建立 但是為了程式碼版本相容, 以及做一些其他包處理操作, 目前還是建議建立 __init__.py檔案作用 第一次匯入這個包的時候, 都會自動的執行這個檔案
建立多層級包
在包裡面直接建立另外一個包即可, 可以無限級巢狀
包/模組的基本資訊
包和模組名稱 模組名稱 去除.py字尾名後的檔名稱 例如 sz.py 是一個模組 模組名稱是 sz
包名
資料夾名稱 包和模組的存放位置 import os print(os.__file__) 會列印os模組所在路徑 檢視包和模組裡面的內容 dir(模組/包名稱) 匯入包/模組的方式 友情提醒 這一塊知識點本身比較碎; 需要自己多做實驗慢慢體會掌握
理論基礎
匯入模組的作用 可以使用這個模組裡面的內容
2.常規匯入
方式 import M 匯入單個模組 解釋 M 模組 如果是某個包裡的模組, 可以通過點語法來定位 import M1, M2 匯入多個模組 解釋 M1 模組 如果是某個包裡的模組, 可以通過點語法來定位 M2 模組 如果是某個包裡的模組, 可以通過點語法來定位 import M as 別名 匯入模組時,給模組起個別名 應用場景 簡化資源訪問字首 例如 原始碼 呼叫資源時 xx1.xx2.xx3.xx4.資源 import xx1.xx2.xx3.xx4 優化後 import xx1.xx2.xx3.xx4 as hehe 呼叫資源時 hehe.資源 增加程式的擴充套件性 例如 if file_extension == "txt": import txt_parse txt_parse.open() txt_parse.read() txt_parse.close() elif file_extension == "doc": import doc_parse doc_parse.open() doc_parse.read() doc_parse.close() 優化後 if file_extension == "txt": import txt_parse as parse elif file_extension == "doc": import doc_parse as parse parse.open() parse.read() parse.close() 注意 使用時,需要指明資源的模組名稱 例如:p1.my_moudle.run() 補充 如果匯入的是一個包 預設不會匯入任何模組 解決方案 1. 在__init__檔案中, 再次匯入需要的模組 2. 應該以from ... import ... 的形式匯入
from語句匯入
作用 想要匯入一個模組或包中的某個部分 從哪裡, 匯入哪些資源到當前位置 語法 from A import B [as C] 理論(sz) 明確一點 只能從大的地方找小的東西 從盆裡面找碗是可以 反之, 從碗裡面找盆就有問題 按照大小順序可以將幾個資源排序 包 > 模組 > 模組資源 注意面向關係 模組裡面只能看到模組資源 最終組合 包裡面只能看到模組 看不到模組資源 1. 從包中匯入模組 單個 多個 起別名 包有多層級 2. 從模組中匯入模組資源 單個 多個 起別名 模組有多層級 注意 保證B部分路徑最簡 原則: 從那裡能看到誰才能匯入誰 舉個栗子 from 大包 import 小包.模組 from 大包.小包 import 模組 from 包 import 模組.子資源 from 包.模組 import 子資源 特例 from 模組 import * * 代表是所有非下劃線_開頭資源匯入到當前位置 配合__all__ 是一個列表 __all__ = ["a", "run", "Person"] 列表中每個元素都是字串 代表到時*能匹配到的資源 慎用 因為你無法預知到時會匯入哪些內容到當前位置,容易產生變數名衝突 from 包 import * 會識別__init__檔案中__all__列表中的指定模組
注意
1. 匯入模組後具體做了什麼事? 第一次匯入時 1. 在自己當下的名稱空間中, 執行所有程式碼 2. 建立一個模組物件, 並將模組內所有頂級變數以屬性的形式繫結在模組物件上 3. 在import的位置, 引入import後面的變數名稱到當前名稱空間 第二次匯入時 直接執行上述第3步 結論 注意: 兩種匯入方式都會大致執行以上的步驟 1. 多次匯入模組, 該模組並不會執行多次 2. 兩種匯入方式不存在哪一種更省記憶體 區別在於把哪一部分內容拿到當前位置來用 2. 從哪個位置找到需要匯入的模組? 第一次匯入時 按照模組檢索路徑順序去找 第一級 內建模組 第二級 sys.path 構成 當前目錄 import os os.getcwd() 環境變數 PYTHONPATH 中指定的路徑列表 特定路徑下的.pth檔案中的檔案路徑列表 檢視特定路徑 import site print(site.getsitepackages()) 字尾名為.pth檔案 名稱隨意 一個路徑佔一行 在 Python 安裝路徑的 lib 庫中搜索 注意 自己測試優先順序順序 追加路徑的方式 1. 直接修改sys.path 只作用於本次 2. 修改環境變數 PYTHONPATH 注意 僅僅在shell中有效 pycharm需要另外一種設定方式 3. 新增.pth檔案 第二次匯入時 從已經載入過的模組中去找 檢視已載入模組 import sys sys.modules 3. 匯入模組的常見場景? 區域性匯入 在某個區域性範圍內匯入模組 在其他範圍無法使用 所以,如果想要全域性範圍都能使用,在檔案頂部匯入相關模組 使用場景 當一個模組使用並不頻繁, 而且匯入時間過長時 覆蓋匯入 場景1 自定義模組和非內建的標準模組重名 根據前者儲存位置, 有可能前者會覆蓋後者 結論 自定義模組命名不要與後者重名 場景2 自定義模組和內建模組重名 內建肯定覆蓋自定義 你又特別想用自定義模組 使用from...import... 指明絕對路徑進行匯入 迴圈匯入 假設有兩個模組A, B 模組A內匯入了模組B; 模組B內也匯入了模組A;這樣就造成了迴圈匯入 可選匯入 概念 兩個功能相近的包, 根據需求優先選擇其中一個匯入 場景 有兩個包A和B都可以實現相同的功能 想優先使用A; 而且需要做到在沒有A的情況下, 使用B做備選 實現 使用try...except...進行實現 包內匯入 絕對匯入和相對匯入 理論 Python 相對匯入與絕對匯入,這兩個概念是相對於包內匯入而言的 包內匯入即是包內的模組匯入包內部的模組 概念 絕對 參照sys.path路徑進行檢索 例如 指明包名或模組名 import a from a import b 注意 以上結論基於Python3.x之後 相對 使用.來指代相對路徑 . 根據模組名稱所獲取的當前目錄 .. 根據模組名稱所獲取的上層目錄 例如 from . import a from .. import a 注意 直譯器是根據模組名稱而確定層級關係, 並不是存放目錄 可以通過__name__來檢視模組名稱 補充 Python3.x版本之前, 直接import a 優先從本地當前目錄查詢, 並非是sys.path 解決方案 from __future__ import absolute_import 使用上述語句, 改變import 行為 結論 正確用法 包內匯入 使用相對匯入 包外匯入 使用絕對匯入
三方包/模組的安裝和升級
理論 1. 為什麼要安裝三方模組? 因為標準模組有時不能滿足我們的需求 2. 三方模組和標準模組的區別和聯絡? 首先,兩者都是為了完成某個功能需求 標準模組 由官方釋出 使用可靠,幾乎沒有bug,即使有也有團隊立即修復 有健全的使用文件說明 三方模組 由網友提供,可能有如下缺點 文件不健全 更新不及時或者根本不更新 功能有bug 3. 為什麼標準模組不做的超級全? 每個人的需求不同,做並集會導致整個檔案非常龐大,你願意一次性下載好幾個G而且有可能根本用不到檔案嗎? 所以,做了需求的交集;大多數人都需要的功能被放到了標準模組 4. 什麼叫模組的安裝? 三方模組本質就是別人寫的程式碼 所謂安裝,就是想辦法把這個程式碼搞到本地,讓我們可以來用 5. 安裝的方式? 原始碼安裝 自己手動去某個地方去下載,然後安裝到本地 包管理器安裝 更加簡單的自動化的為使用者安裝管理包和模組 只需要一個或幾個命令就可以完成 6. 包管理專案簡史 distutils 產生背景 三方庫的存在是必然 為了讓使用者更好的使用和管理三方庫,官方就開發了這個專案 1998-2000 角色定位 屬於Python標準庫(官方發行) 功能特點 只需要通過合適的命令執行一個叫做setup.py的檔案即可 只能處理簡單的包安裝 setuptools 產生背景 自從distutils開發停止之後,一些開發人員在它的基礎之上進行開發自己的工具 其中最成功的的就是setuptools 說明還有其他很多不太成功的 角色定位 屬於三方庫 功能特點 更加頻繁的更新 更多的高階功能 自動依賴處理 egg分發格式 easy_install命令 與distutils的相容 distribute 產生背景 setuptools開發變緩慢了(不支援Python3),以為會如同distutils一樣停止開發 另一批開發人員又基於setuptools(fork)建立了名為distribute的庫 角色定位 依然是三方庫 功能特點 bug更少 支援Python3 現狀 2013年setuptools和distribute兩個開發組織決定再次合併到setuptools專案中 所以,distribute被廢棄 setuptools又成了正主 ... 目前為止有很多包管理工具 disutils2 distlib ... 但是官方支援的且認可度高的就兩個 distutils 官方標準庫 從python2 到python3.6全部內建支援 setuptools(合併distribute後的) 三方庫 部分 Python 子社群已然是事實上的標準 更多包管理專案請看 https://packaging.python.org/key_projects/ 總結 distutils 是標準庫的一部分 能處理簡單的包的安裝 通過setup.py進行安裝 setuptools 現在的包安裝標準 曾經差點被廢棄,現在有繼續開發 自帶了一個easy_install 安裝指令碼 後來出現個更牛逼的pip安裝指令碼來替代它 引入了.egg格式 後來出現個更好的whl格式來代替它 setuptools是目前的主要選擇 7. 常見已釋出三方包和模組的形式? 原始碼 單檔案模組 多檔案模組(由包管理工具釋出的專案) 基於distutils工具釋出的專案特點 包含setup.py檔案 setuptools也是基於distutils .egg setuptools引入的一種格式 setuptools可以識別它,安裝它 .whl 本質是.zip格式 是為了替代egg 8. 安裝方式 本地安裝 對於單檔案模組 直接拷貝到相關資料夾就可以 對於帶setup.py的檔案 通過setup.py 指令碼即可安裝 .egg檔案 使用setuptools的自帶的安裝指令碼 easy_install進行安裝 .whl 使用pip進行安裝 遠端安裝 easy_install pip pycharm 安裝源 Python官方 https://pypi.python.org/simple 豆瓣 http://pypi.douban.com/simple/ 阿里 http://mirrors.aliyun.com/pypi/simple/ 中國科學技術大學 https://pypi.mirrors.ustc.edu.cn/simple/ 伺服器在國外,所以國內訪問有可能非常慢,網路不好 映象地址,伺服器在國內,所以網路比較通暢,速度快!
模組安裝的具體操作
本地安裝 對於單檔案模組 直接拷貝到相關資料夾就可以 存放位置 sys.path中所包含的路徑都可以 一般存放在Lib/site-package資料夾中 對於帶setup.py的檔案 步驟1 開啟命令列工具 步驟2 切換到setup.py檔案所在的目錄 步驟3 執行命令python setup.py install Python2.x 執行命令python3 setup.py install Python3.x 注意 如果專案是使用distutils打包的,上述命令可以直接使用 因為distutils是Python自帶模組,不需要安裝 如果專案是使用setuptools打包的,有可能上述命令會報錯 錯誤 原因 setuptools屬於三方模組,並非標準模組,所以有可能沒有安裝 解決方案 安裝setuptools 離線安裝 但是有時候, 包, 依賴的三方包 依然需要聯網, 讓它自動的給我們下載安裝這些三方的包 .egg檔案 使用setuptools的自帶的安裝指令碼 easy_install進行安裝 要求先安裝setuptools 語法 easy_install xxx.egg .whl 使用easy_install安裝 語法 easy_install xxx.whl 使用pip進行安裝 推薦 安裝pip 通過easy_install 遠端或者本地安裝 遠端 easy_install pip 自動下載,自動安裝 本地 .egg .whl .tar.gz 語法 pip install xxx.whl 遠端安裝 概念 自動的從遠端地址檢索->下載->安裝某個模組 安裝方式 easy_install xxx 需要先安裝setuptools pip install xxx 需要先安裝pip 疑問 從哪個地方下載的包安裝到本地的? 預設:https://pypi.python.org/ 安裝在本地的哪個地方了? 一般在Lib/site_packages
模組的其他操作
easy_install
詳細介紹地址 http://peak.telecommunity.com/DevCenter/EasyInstall 其他常用操作 多個Python版本的切換安裝 場景 如果一臺電腦上,既裝了Python2.x 也裝了 Python3.x 兩個版本環境都裝了setuptools, 都可以使用easy_install 那麼,到時候,如何通過easy_install 安裝到指定版本的環境中? 解決方案 easy_install-N.N N.N用於指明安裝在哪個Python版本環境中 例如 Python2.7.14 easy_install-2.7 requests Python3.6.3 easy_install-3.6 requests 安裝指定版本包 場景 如果一個包有多個版本;而有的專案使用的是某個特定版本,那該如何安裝? 解決方案 easy_install “庫名 限定符 版本[, 限定符 版本]” 中括號部分代表可選 庫名 包的名稱 限定符 < > <= >= == 例如 easy_install "requests >= 2.14.1" 安裝大於或等於2.14.1版本的最新包 easy_install "requests > 1.0, < 2.0" 安裝大於1.0 並且小於 2.0的包 easy_install "requests == 2.14.1" 安裝2.14.1版本的包 如果已經安裝,則切換到這個版本 ... 升級三方包 場景 有些包的作者,修復了之前的某個Bug; 本地需要更新到最新版本 解決方案 easy_install --upgrade(-U) 庫名 例如 easy_install --upgrade requests 解除安裝三方包 場景 有些已經安裝的包,因某些原因,想要刪除(比如:使用這個包的專案已經不需要) 解決方案 方式1:手動解除安裝 刪除在easy_install.pth中的包記錄 刪除對應的包檔案 方式2:easy_install -m 包名稱 效果 刪除在easy_install.pth檔案中對應包的記錄 注意 並沒有真正的把.egg包檔案刪除 不刪除原因 方便多版本切換 強迫症選手可以選擇手動刪除 不會刪除依賴包 本身也不應該刪除 因為這個依賴包,有可能也被其他三方包依賴 補充 easy_install.pth作用 記錄著當前通過easy_isntall已經安裝的模組 多個版本的模組,值記錄最後一次安裝的 用於匯入模組時的路徑檢索 -m的真正含義 支援多版本,可在執行時進行切換 easy_install.pth 對應的庫的記錄刪除 解釋 不直接指明包的某個版本,使得使用者無法直接匯入 刪除在easy_install.pth檔案中對應包的記錄 使用者如果想使用某個版本,需要使用如下步驟 import pkg_resources pkg_resources.require("requests==2.18.4") import requests 切換三方安裝源 場景 有可能Python官方庫的託管平臺,伺服器在國外的原因,會導致安裝速度慢,甚至失敗 解決方案 easy_install修改檔案 setuptools\command\easy_install.py 安裝源 Python官方 https://pypi.python.org/simple 豆瓣 http://pypi.douban.com/simple/ 阿里 http://mirrors.aliyun.com/pypi/simple/ 中國科學技術大學 https://pypi.mirrors.ustc.edu.cn/simple/ 伺服器在國外,所以國內訪問有可能非常慢,網路不好 映象地址,伺服器在國內,所以網路比較通暢,速度快!
pip
詳細介紹地址 https://pip.pypa.io/en/stable/ 其他常用操作 切換安裝源 一次性修改 pip install --index-url https://pypi.douban.com/simple/ requests 指定檢索 僅僅只到某一個地址檢索指定包 pip install --extra-index-url https://pypi.douban.com/simple/ requests 擴充套件檢索 除下到官方的pypi地址檢索,也會到擴充套件的地址檢索 永久性修改 在c://users/你的使用者名稱/下 建立pip資料夾 在pip資料夾中建立pip.ini檔案 檔案內容 [global] index-url = http://pypi.douban.com/simple/ [install] trusted-host=pypi.douban.com 安裝源 Python官方 https://pypi.python.org/simple 豆瓣 http://pypi.douban.com/simple/ 阿里 http://mirrors.aliyun.com/pypi/simple/ 中國科學技術大學 https://pypi.mirrors.ustc.edu.cn/simple/ 伺服器在國外,所以國內訪問有可能非常慢,網路不好 映象地址,伺服器在國內,所以網路比較通暢,速度快! 安裝在不同的Python版本環境中 方式1 python -m pip install requests python3 -m pip install requests 方式2 py -2 -m pip install requests py -3 -m pip install requests 理論 Python的安裝包實際上在系統中安裝了一個啟動器py.exe C:\Windows\py.exe 啟動器可以呼叫不同版本的Python去執行某些指令碼 py -2 py -3 檢視包 所有已經安裝的 pip list 不被依賴的包 pip list --not-required 過期的包 pip list --outdated 檢視某個包的具體資訊 pip show xxx 搜尋包 pip search xxx pip search -i 檢索地址 xxx 預設為Python官方的庫地址 https://pypi.python.org/simple 例如 pip search peppercorn 安裝特定版本 pip install "requests == 2.18" pip install "requests >= 2.0" pip install "requests > 2.0, < 3.0" 升級包 pip install --upgrade xxx 注意 pip install xxx 表示:只有當xxx庫不存在的時候,才會安裝最新版本 解除安裝包 pip uninstall xxx 如果是通過easy_install安裝的 會自動刪除easy_install.pth檔案中對應包路徑 會自動刪除對應.egg包的原檔案 如果是通過pip install 安裝的,會直接刪除對應包檔案 生成凍結需求文字 場景 可以將當前安裝的三方包記錄,儲存到指定的檔案當中 以後,就可以根據這個需求文字,去安裝三方包 用法 pip freeze > requirements.txt 用來將當前環境下安裝的三方包輸出到指定檔案中 因為輸出的檔案,以後是為了讓別人通過pip安裝 所以,能看到的列表中自動過濾了pip, setuptools 可通過 --all引數檢視所有包 根據凍結需求文字安裝 pip install -r requirements.txt
補充
三方模組的版本規則 三部分組成n1.n2.n3 n3 當版本的bug修復之後,n3 + 1 n2 新增了某一個小功能 n2 + 1 n1 修改了之前的功能,或者, 添加了一個新功能(修改了之前的api) n1 + 1 1. 我釋出了一個庫 1.0.0 2.之前釋出的庫, 出現了一個bug, 然後我再本地修復了這個bug, 並且進行再次的釋出 1.0.1 3. 往後, 在這個庫裡面, 新增了一個小功能 1.1.0 4.發現1.1.0版本出現了一個bug, 修復 -》 釋出 1.1.1 4. 新增一個小功能 1.2.0 6. 釋出了一個超級大的功能, api, 釋出 2.0.0 ``