充分理解 python -m mod

最近在看 __main__ 的官方文檔 —— https://docs.python.org/3/library/__main__.html#module-__main__,提到一個 python -m 的用法,非常不理解,因此查找了不少文檔,並進行了以下總結。

查看 Python 的 help 內容

$ python --help
...
-m mod : run library module as a script (terminates option list)
# 直譯就是按照腳本的方式執行模塊
...

有無 -m 參數的比較

1. python script.py # 直接執行腳本
2. python -m script.py # 當作模塊的方式執行,至關於 import

通常狀況下,咱們會想固然的認爲,有無參數 -m 對程序會有不一樣的影響,可是很惋惜,第二種寫法是會在程序執行以後報錯的。其正確的寫法是:丟掉 .py 後綴html

首先直觀的觀察執行結果,Python 的版本是 3.6.3
編寫 script.py 腳本,內容以下:python

import sys
print(sys.path)
print(sys.modules)

直接執行腳本app

$ python script.py
['/home/ossifrage/workspaces/python-m', '/usr/lib/python36.zip', '/usr/lib/python3.6', ...]
{..., '__main__': <module '__main__' from 'script.py'>, ...}

當作模塊方式執行spa

$ python -m script
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', ...]
{..., '__main__': <module 'run' from '/home/ossifrage/workspaces/python-m/script.py'>, ..., 'runpy': <module 'runpy' from '/usr/lib/python3.6/runpy.py'>, 'pkgutil': <module 'pkgutil' from '/usr/lib/python3.6/pkgutil.py'>}

顯示的內容還有不少,只突出顯示出了不一樣的地方。命令行

經過比較不一樣的地方,咱們發現:code

第一種方法——直接運行腳本,當前腳本所在的路徑會加入到 sys.path 列表中,可是 sys.modules 字典中的 __main__ 的路徑不是絕對路徑,只是腳本名稱htm

第二種方法——當作模塊方式運行,當前腳本所在的路徑不會加入到 sys.path 列表中,可是 sys.modules 字典中的 __main__ 的路徑是絕對路徑,同時,還引入了 runpypkgutil 兩個模塊blog

runpy 的用途:定位並執行該模塊。主要用途在於實現命令行 -m 執行 python 模塊的效果。ip

pkgutil 的用途:獲取包裏面的全部模塊列表。pkgutil.get_data() 可讀取包內任何文件內容。內存

模塊的導入機制

其實,上面的內容涉及到了 Python 包模塊的導入機制。

要理解模塊的導入機制,得理解幾個關鍵的名詞。sys.path -> sys.modules -> < module >.__dict__。

sys.path:是一個列表。保存着模塊的搜索路徑。若是路徑沒有存在與該列表中,可以使用 sys.path.append() 導入。

sys.modules: 是一個字典。全部加載到內存中的模塊都存放在該字典中。當 import 一個模塊的時候,首先會在這個字典中查找是否已經加載了目標模塊。若是已加載,則將模塊的名字加入到正在調用 import 的模塊的 Local 命名空間(也就是< module >.__dict__)中。若是沒有,則從 sys.path 查找,找到後載入內存,並加入到 sys.modules 字典,名稱也將導入到當前模塊的 Local 命名空間。

reference

相關文章
相關標籤/搜索