欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python 中 -m 的典型用法、原理解析與發(fā)展演變

 更新時間:2019年11月11日 14:32:26   作者:豌豆花下貓  
這篇文章主要介紹了Python 中 -m 的典型用法、原理解析與發(fā)展演變,需要的朋友可以參考下

在命令行中使用 Python 時,它可以接收大約 20 個選項(option),語法格式如下:

python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]

本文想要聊聊比較特殊的“-m”選項: 關(guān)于它的典型用法、原理解析與發(fā)展演變的過程。

首先,讓我們用“--help”來看看它的解釋:

-m mod run library module as a script (terminates option list)

"mod"是“module”的縮寫,即“-m”選項后面的內(nèi)容是 module(模塊),其作用是把模塊當(dāng)成腳本來運行。

“terminates option list”意味著“-m”之后的其它選項不起作用,在這點上它跟“-c”是一樣的,都是“終極選項”。官方把它們定義為“接口選項”(Interface options),需要區(qū)別于其它的普通選項或通用選項。

-m 選項的五個典型用法

Python 中有很多使用 -m 選項的場景,相信大家可能會用到或者看見過,我在這里想分享 5 個。

在 Python3 中,只需一行命令就能實現(xiàn)一個簡單的 HTTP 服務(wù):

python -m http.server 8000

# 注:在 Python2 中是這樣
python -m SimpleHTTPServer 8000

執(zhí)行后,在本機打開“ http://localhost:8000  ”,或者在局域網(wǎng)內(nèi)的其它機器上打開“  http://本機ip:8000   ”,就能訪問到執(zhí)行目錄下的內(nèi)容,例如下圖就是我本機的內(nèi)容:

與此類似,我們只需要一行命令“python -m pydoc -p xxx”,就能生成 HTML 格式的官方幫助文檔,可以在瀏覽器中訪問。

上面的命令執(zhí)行了 pydoc 模塊,會在 9000 端口啟動一個 http 服務(wù),在瀏覽器中打開,我的結(jié)果如下:

它的第三個常見用法是執(zhí)行 pdb 的調(diào)試命令“python -m pdb xxx.py”,以調(diào)試模式來執(zhí)行“xxx.py”腳本:

第四個同樣挺有用的場景是用 timeit 在命令行中測試一小段代碼的運行時間。以下的 3 段代碼,用不同的方式拼接 “0-1-2-……-99” 數(shù)字串??梢灾庇^地看出它們的效率差異:

最后,還有一種常常被人忽略的場景:“python -m pip install xxx”。我們可能會習(xí)慣性地使用“pip install xxx”,或者做了版本區(qū)分時用“pip3 install xxx”,總之不在前面用“python -m”做指定。但這種寫法可能會出問題。

很巧合的是,在本月初(2019.11.01),Python 的核心開發(fā)者、第一屆指導(dǎo)委員會 五人成員之一的 Brett Cannon 專門寫了一篇博客《 Why you should use "python -m pip" 》,提出應(yīng)該使用“python -m pip”的方式,并做了詳細的解釋。

他的主要觀點是:在存在多個 Python 版本的環(huán)境中,這種寫法可以精確地控制三方庫的安裝位置。例如用“python3.8 -m pip”,可以明確指定給 3.8 版本安裝,而不會混淆成其它的版本。

(延伸閱讀:關(guān)于 Brett 的文章,這有一篇簡短的歸納《 原來我一直安裝 Python 庫的姿勢都不對呀! 》)

-m 選項的兩種原理解析

看了前面的幾種典型用法,你是否開始好奇: “-m”是怎么運作的?它是怎么實現(xiàn)的?

對于“python -m name”,一句話解釋: Python 會檢索 sys.path ,查找名字為“name”的模塊或者包(含命名空間包),并將其內(nèi)容當(dāng)成“__main__”模塊來執(zhí)行。

1、對于普通模塊

以“.py”為后綴的文件就是一個模塊,在“-m”之后使用時,只需要使用模塊名,不需要寫出后綴,但前提是該模塊名是有效的,且不能是用 C 語言寫成的模塊。

在“-m”之后,如果是一個無效的模塊名,則會報錯“No module named xxx”。

如果是一個帶后綴的模塊,則首先會導(dǎo)入該模塊,然后可能報錯:Error while finding module specification for 'xxx.py' (AttributeError: module 'xxx' has no attribute '__path__'。

對于一個普通模塊,有時候這兩種寫法表面看起來是等效的:

兩種寫法都會把定位到的模塊腳本當(dāng)成主程序入口來執(zhí)行,即在執(zhí)行時,該腳本的 __name__ 都是”__main__“,跟 import 導(dǎo)入方式是不同的。

但它的前提是:在執(zhí)行目錄中存在著“test.py”,且只有唯一的“test”模塊。對于本例,如果換一個目錄執(zhí)行的話,“python test.py”當(dāng)然會報找不到文件的錯誤,然而,“python -m test”卻不會報錯,因為解釋器在遍歷 sys.path 時可以找到同名的“test”模塊,并且執(zhí)行:

由此差異,我們其實可以總結(jié)出“-m”的用法: 已知一個模塊的名字,但不知道它的文件路徑,那么使用“-m”就意味著交給解釋器自行查找,若找到,則當(dāng)成腳本執(zhí)行。

以前文的“python -m http.server 8000”為例,我們也可以找到“server”模塊的絕對路徑,然后執(zhí)行,盡管這樣會變得很麻煩。

那么,“-m”方式與直接運行腳本相比,在實現(xiàn)上有什么不同呢?

直接運行腳本時,相當(dāng)于給出了腳本的完整路徑(不管是絕對路徑還是相對路徑),解釋器根據(jù) 文件系統(tǒng)的查找機制, 定位到該腳本,然后執(zhí)行 使用“-m”方式時,解釋器需要在不 import 的情況下,在 所有模塊命名空間 中查找,定位到腳本的路徑,然后執(zhí)行。為了實現(xiàn)這個過程,解釋器會借助兩個模塊: pkgutilrunpy ,前者用來獲取所有的模塊列表,后者根據(jù)模塊名來定位并執(zhí)行腳本 2、對于包內(nèi)模塊

如果“-m”之后要執(zhí)行的是一個包,那么解釋器經(jīng)過前面提到的查找過程,先定位到該包,然后會去執(zhí)行它的“__main__”子模塊,也就是說,在包目錄下需要實現(xiàn)一個“__main__.py”文件。

換句話說,假設(shè)有個包的名稱是“pname”,那么, “python -m pname”,其實就等效于“python -m pname.__main__”。

仍以前文創(chuàng)建 HTTP 服務(wù)為例,“http”是 Python 內(nèi)置的一個包,它沒有“__main__.py”文件,所以使用“-m”方式執(zhí)行時,就會報錯:No module named http.__main__; 'http' is a package and cannot be directly executed。

作為對比,我們可以看看前文提到的 pip,它也是一個包,為什么“python -m pip”的方式可以使用呢?當(dāng)然是因為它有“__main__.py”文件:

“python -m pip”實際上執(zhí)行的就是這個“__main__.py”文件,它主要作為一個調(diào)用入口,調(diào)用了核心的"pip._internal.main"。

http 包因為沒有一個統(tǒng)一的入口模塊,所以采用了“python -m 包.模塊”的方式,而 pip 包因為有統(tǒng)一的入口模塊,所以加了一個“__main__.py”文件,最后只需要寫“python -m 包”,簡明直觀。

-m 選項的十年演變過程

最早引入 -m 選項的是 Python 2.4 版本(2004年),當(dāng)時功能還挺受限,只能作用于普通的內(nèi)置模塊(如 pdb 和 profile)。

隨后,知名開發(fā)者 Nick Coghlan 提出的《PEP 338 -- Executing modules as scripts 》把它的功能提升了一個臺階。這個 PEP 在 2004 年提出,最終實現(xiàn)在 2006 年的 2.5 版本。

(插個題外話:Nick Coghlan 是核心開發(fā)者中的核心之一,也是第一屆指導(dǎo)委員會的五人成員之一。記得當(dāng)初看材料,他是在 2005 年被選為核心開發(fā)者的,這時間與 PEP-338 的時間緊密貼合)

這個 PEP 的幾個核心點是:

  • 結(jié)合了 PEP-302 的新探針機制(new import hooks),提升了解釋器查找包內(nèi)模塊的能力
  • 結(jié)合了其它的導(dǎo)入機制(例如 zipimport 和凍結(jié)模塊(frozen modules)),拓展了解釋器查找模塊的范圍與精度
  • 開發(fā)了新的 runpy.run_module(modulename) 來實現(xiàn)本功能,而不用修改 CPython 解釋器,如此可方便移植到其它解釋器

至此,-m 選項使得 Python 可以在所有的命名空間內(nèi)定位到命令行中給定的模塊。

2009 年,在 Python 3.1 版本中,只需給定包的名稱,就能定位和運行它的“__main__”子模塊。2014 年,-m 擴展到支持命名空間包。

至此,經(jīng)過十年的發(fā)展演變,-m 選項變得功能齊全,羽翼豐滿。

最后,我們來個 ending 吧:-m 選項可能看似不起眼,但它絕對是最特別的選項之一,它使得在命令行中,使用內(nèi)置模塊、標(biāo)準包與三方庫時變得更輕松便利。有機會就多用一下吧,體會它帶來的愉悅體驗。

參考材料

https://docs.python.org/3.7/using/cmdline.html#cmdoption-m

https://snarky.ca/why-you-should-use-python-m-pip

https://www.python.org/dev/peps/pep-0338/

總結(jié)

以上所述是小編給大家介紹的Python 中 -m 的典型用法、原理解析與發(fā)展演變,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

相關(guān)文章

  • 深入理解Python 關(guān)于supper 的 用法和原理

    深入理解Python 關(guān)于supper 的 用法和原理

    這篇文章主要介紹了Python 關(guān)于supper 的 用法和原理分析,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2018-02-02
  • 詳解Python3遷移接口變化采坑記

    詳解Python3遷移接口變化采坑記

    這篇文章主要介紹了詳解Python3遷移接口變化采坑記,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Tkinter使用Progressbar創(chuàng)建和管理進度條的操作代碼

    Tkinter使用Progressbar創(chuàng)建和管理進度條的操作代碼

    Progressbar是Tkinter庫中的一個小部件,用于創(chuàng)建和管理進度條,這篇文章主要介紹了Tkinter使用Progressbar創(chuàng)建和管理進度條,本文結(jié)合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • python實現(xiàn)多進程通信實例分析

    python實現(xiàn)多進程通信實例分析

    這篇文章主要介紹了python實現(xiàn)多進程通信實例分析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Python機器學(xué)習(xí)NLP自然語言處理基本操作新聞分類

    Python機器學(xué)習(xí)NLP自然語言處理基本操作新聞分類

    本文是Python機器學(xué)習(xí)NLP自然語言處理系列文章,開始我們自然語言處理 (NLP) 的學(xué)習(xí)旅程. 本文主要學(xué)習(xí)NLP自然語言處理基本操作新聞分類
    2021-09-09
  • 詳解Python3的TFTP文件傳輸

    詳解Python3的TFTP文件傳輸

    本篇內(nèi)容給大家詳細講述了Python3的TFTP文件傳輸?shù)南嚓P(guān)知識點,有需要的朋友可以參考下。
    2018-06-06
  • python人工智能使用RepVgg實現(xiàn)圖像分類示例詳解

    python人工智能使用RepVgg實現(xiàn)圖像分類示例詳解

    這篇文章主要介紹了python人工智能使用RepVgg實現(xiàn)圖像分類示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Python3正則匹配re.split,re.finditer及re.findall函數(shù)用法詳解

    Python3正則匹配re.split,re.finditer及re.findall函數(shù)用法詳解

    這篇文章主要介紹了Python3正則匹配re.split,re.finditer及re.findall函數(shù)用法,結(jié)合實例形式詳細分析了正則匹配re.split,re.finditer及re.findall函數(shù)的概念、參數(shù)、用法及操作注意事項,需要的朋友可以參考下
    2018-06-06
  • python3射線法判斷點是否在多邊形內(nèi)

    python3射線法判斷點是否在多邊形內(nèi)

    這篇文章主要為大家詳細介紹了python3射線法判斷點是否在多邊形內(nèi),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • python中uuid模塊實例淺析

    python中uuid模塊實例淺析

    在本篇文章里小編給大家整理了一篇關(guān)于python中uuid模塊實例淺析內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2020-12-12

最新評論