runpy ——查找并執行 Python 模塊?

源代碼: Lib/runpy.py


runpy 模塊用于找到并運行 Python 的模塊,而無(wú)需首先導入。主要用于實(shí)現 -m 命令行開(kāi)關(guān),以允許用 Python 模塊命名空間而不是文件系統來(lái)定位腳本。

請注意,這 并非 一個(gè)沙盒模塊——所有代碼都在當前進(jìn)程中運行,所有副作用(如其他模塊對導入操作進(jìn)行了緩存)在函數返回后都會(huì )留存。

此外,在 runpy 函數返回后,任何由已執行代碼定義的函數和類(lèi)都不能保證正確工作。如果某使用場(chǎng)景不能接收此限制,那么選用 importlib 可能更合適些。

runpy 模塊提供兩個(gè)函數:

runpy.run_module(mod_name, init_globals=None, run_name=None, alter_sys=False)?

執行給定模塊的代碼,并返回結果模塊的 globals 字典。 該模塊的代碼首先會(huì )用標準的導入機制去查找定位 (詳情請參閱 PEP 302),然后在全新的模塊命名空間中運行。

參數 mod_name 應該是一個(gè)絕對模塊名。如果模塊名指向一個(gè)包,而不是普通的模塊,那么該包會(huì )被導入,然后執行包中的 __main__ 子模塊,并返回結果模塊的 globals 字典。

可選的字典參數 init_globals 可用來(lái)在代碼執行前預填充模塊的 globals 字典。給出的字典參數不會(huì )被修改。如果字典中定義了以下任意一個(gè)特殊全局變量,這些定義都會(huì )被 run_module() 覆蓋。

The special global variables __name__, __spec__, __file__, __cached__, __loader__ and __package__ are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail).

若可選參數 __name__ 不為 None 則設為 run_name,若此名稱(chēng)的模塊是一個(gè)包則設為 mod_name + '.__main__',否則設為 mod_name 參數。

__spec__ 將設為合適的 實(shí)際 導入模塊(也就是說(shuō),__spec__.name 一定是 mod_namemod_name + '.__main__,而不是 run_name)。

__file__ 、__cached__、 __loader____package__ 根據模塊規格進(jìn)行 常規設置

如果給出了參數 alter_sys 并且值為 True,那么 sys.argv[0] 將被更新為 __file__ 的值,sys.modules[__name__] 將被更新為臨時(shí)模塊對象。在函數返回前, sys.argv[0]sys.modules[__name__] 將會(huì )復原。

注意,這種對 sys 的操作不是線(xiàn)程安全的。其他線(xiàn)程可能會(huì )看到初始化不完整的模塊,以及變動(dòng)后的參數列表。如果從線(xiàn)程中的代碼調用此函數,建議單實(shí)例運行 sys 模塊。

參見(jiàn)

-m 選項由命令行提供相同功能。

在 3.1 版更改: 加入了 查找 __main__ 子模塊并執行軟件包的能力。

在 3.2 版更改: 加入了 __cached__ 全局變量(參見(jiàn) PEP 3147 )。

在 3.4 版更改: 充分利用 PEP 451 加入的模塊規格功能。使得以這種方式運行的模塊能夠正確設置 __cached__,并確保真正的模塊名稱(chēng)總是可以通過(guò) __spec__.name 的形式訪(fǎng)問(wèn)。

runpy.run_path(path_name, init_globals=None, run_name=None)?

執行指定位置的代碼,并返回結果模塊的 globals 字典。與提供給 CPython 命令行的腳本名稱(chēng)一樣,給出的路徑可以指向 Python 源文件、編譯過(guò)的字節碼文件或包含``__main__`` 模塊的有效 sys.path 項(例如一個(gè)包含頂級``__main__.py`` 文件的 zip 文件)。

對于直接的腳本而言,指定代碼將直接在一個(gè)新的模塊命名空間中運行。對于一個(gè)有效的 sys.path 項(通常是一個(gè) zip 文件或目錄),其首先會(huì )被添加到 sys.path 的開(kāi)頭。然后,本函數用更新后的路徑查找并執行 __main__ 模塊。請注意,即便在指定位置不存在主模塊,也沒(méi)有特別的保護措施來(lái)防止調用存在于 sys.path 其他地方的 __main__。

利用可選的字典參數 init_globals ,可在代碼執行前預填模塊的 globals 字典。給出的字典參數不會(huì )被修改。如果給出的字典中定義了下列特殊全局變量,這些定義均會(huì )被 run_module() 覆蓋。

The special global variables __name__, __spec__, __file__, __cached__, __loader__ and __package__ are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail).

如果該可選參數不為 None,則 __name__ 被設為 run_name,否則為 '<run_path>'。

如果提供的路徑直接引用了一個(gè)腳本文件(無(wú)論是源碼文件還是預編譯的字節碼),那么 __file__ 將設為給出的路徑,而 __spec__、__cached__、__loader____package__ 都將設為 None。

如果給出的路徑是對有效 sys.path 項的引用,那么 __spec__ 將為導入的 __main__ 模塊進(jìn)行正確設置 (也就是說(shuō),__spec__.name 將一定是 __main__)。 __file__, __cached__, __loader____package__ 將依據模塊規格 進(jìn)行常規設置。

A number of alterations are also made to the sys module. Firstly, sys.path may be altered as described above. sys.argv[0] is updated with the value of path_name and sys.modules[__name__] is updated with a temporary module object for the module being executed. All modifications to items in sys are reverted before the function returns.

注意,與 run_module() 不同的是,本函數對 sys 的修改不是可有可無(wú)的,因為這些調整對于 sys.path 項能夠順利執行至關(guān)重要。由于依然存在線(xiàn)程安全的限制,在線(xiàn)程代碼中使用本函數時(shí)應采用導入鎖進(jìn)行序列運行,或者委托給一個(gè)單獨的進(jìn)程。

參見(jiàn)

接口選項 用于在命令行上實(shí)現同等功能(python path/to/script)。

3.2 新版功能.

在 3.4 版更改: 已作更新,以便充分利用 PEP 451 加入的模塊規格功能。使得從有效 sys.path 項導入``__main__`` 而不是直接執行的情況下,能夠正確設置 __cached__。

參見(jiàn)

PEP 338 -- 將模塊作為腳本執行

PEP 由 Nick Coghlan 撰寫(xiě)并實(shí)現。

PEP 366 ——主模塊的顯式相對導入

PEP 由 Nick Coghlan 撰寫(xiě)并實(shí)現。

PEP 451 —— 導入系統采用的 ModuleSpec 類(lèi)型

PEP 由 Eric Snow 撰寫(xiě)并實(shí)現。

命令行與環(huán)境 —— CPython 命令行詳解

importlib.import_module() 函數