subprocess --- 子進程管理?
源代碼: Lib/subprocess.py
subprocess 模塊允許你生成新的進程,連接它們的輸入、輸出、錯誤管道,并且獲取它們的返回碼。此模塊打算代替一些老舊的模塊與功能:
os.system
os.spawn*
在下面的段落中,你可以找到關于 subprocess 模塊如何代替這些模塊和功能的相關信息。
參見
PEP 324 -- 提出 subprocess 模塊的 PEP
使用 subprocess 模塊?
推薦的調用子進程的方式是在任何它支持的用例中使用 run() 函數。對于更進階的用例,也可以使用底層的 Popen 接口。
run() 函數是在 Python 3.5 被添加的;如果你需要與舊版本保持兼容,查看 較舊的高階 API 段落。
-
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)? 運行被 arg 描述的指令。等待指令完成,然后返回一個
CompletedProcess實例。以上顯示的參數僅僅是最簡單的一些,下面 常用參數 描述(因此在縮寫簽名中使用僅關鍵字標示)。完整的函數頭和
Popen的構造函數一樣,此函數接受的大多數參數都被傳遞給該接口。(timeout, input, check 和 capture_output 除外)。如果 capture_output 設為 true,stdout 和 stderr 將會被捕獲。在使用時,內置的
Popen對象將自動用stdout=PIPE和stderr=PIPE創建。stdout 和 stderr 參數不應當與 capture_output 同時提供。如果你希望捕獲并將兩個流合并在一起,使用stdout=PIPE和stderr=STDOUT來代替 capture_output。timeout 參數將被傳遞給
Popen.communicate()。如果發生超時,子進程將被殺死并等待。TimeoutExpired異常將在子進程中斷后被拋出。input 參數將被傳遞給
Popen.communicate()以及子進程的 stdin。 如果使用此參數,它必須是一個字節序列。 如果指定了 encoding 或 errors 或者將 text 設置為True,那么也可以是一個字符串。 當使用此參數時,在創建內部Popen對象時將自動帶上stdin=PIPE,并且不能再手動指定 stdin 參數。如果 check 設為 True, 并且進程以非零狀態碼退出, 一個
CalledProcessError異常將被拋出. 這個異常的屬性將設置為參數, 退出碼, 以及標準輸出和標準錯誤, 如果被捕獲到.如果 encoding 或者 error 被指定, 或者 text 被設為 True, 標準輸入, 標準輸出和標準錯誤的文件對象將通過指定的 encoding 和 errors 以文本模式打開, 否則以默認的
io.TextIOWrapper打開. universal_newline 參數等同于 text 并且提供了向后兼容性. 默認情況下, 文件對象是以二進制模式打開的.如果 env 不是
None, 它必須是一個字典, 為新的進程設置環境變量; 它用于替換繼承的當前進程的環境的默認行為. 它將直接被傳遞給Popen.示例:
>>> subprocess.run(["ls", "-l"]) # doesn't capture output CompletedProcess(args=['ls', '-l'], returncode=0) >>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 >>> subprocess.run(["ls", "-l", "/dev/null"], capture_output=True) CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n', stderr=b'')
3.5 新版功能.
在 3.6 版更改: 添加了 encoding 和 errors 形參.
在 3.7 版更改: 添加了 text 形參, 作為 universal_newlines 的一個更好理解的別名. 添加了 capture_output 形參.
-
class
subprocess.CompletedProcess? run()的返回值, 代表一個進程已經結束.-
args? 被用作啟動進程的參數. 可能是一個列表或字符串.
-
returncode? 子進程的退出狀態碼. 通常來說, 一個為 0 的退出碼表示進程運行正常.
一個負值
-N表示子進程被信號N中斷 (僅 POSIX).
-
stdout? 從子進程捕獲到的標準輸出. 一個字節序列, 或一個字符串, 如果
run()是設置了 encoding, errors 或者text=True來運行的. 如果未有捕獲, 則為None.如果你通過
stderr=subprocess.STDOUT運行進程,標準輸入和標準錯誤將被組合在這個屬性中,并且stderr將為None。
-
stderr? 捕獲到的子進程的標準錯誤. 一個字節序列, 或者一個字符串, 如果
run()是設置了參數 encoding, errors 或者text=True運行的. 如果未有捕獲, 則為None.
-
check_returncode()? 如果
returncode非零, 拋出CalledProcessError.
3.5 新版功能.
-
-
subprocess.DEVNULL? 可被
Popen的 stdin, stdout 或者 stderr 參數使用的特殊值, 表示使用特殊文件os.devnull.3.3 新版功能.
-
subprocess.PIPE? 可被
Popen的 stdin, stdout 或者 stderr 參數使用的特殊值, 表示打開標準流的管道. 常用于Popen.communicate().
-
exception
subprocess.SubprocessError? 此模塊的其他異常的基類。
3.3 新版功能.
-
exception
subprocess.TimeoutExpired? SubprocessError的子類,等待子進程的過程中發生超時時被拋出。-
cmd? 用于創建子進程的指令。
-
timeout? 超時秒數。
-
output? 子進程的輸出, 如果被
run()或check_output()捕獲。否則為None。
3.3 新版功能.
在 3.5 版更改: 添加了 stdout 和 stderr 屬性。
-
-
exception
subprocess.CalledProcessError? SubprocessError的子類,當一個被check_call()或check_output()函數運行的子進程返回了非零退出碼時被拋出。-
returncode? 子進程的退出狀態。如果程序由一個信號終止,這將會被設為一個負的信號碼。
-
cmd? 用于創建子進程的指令。
-
output? 子進程的輸出, 如果被
run()或check_output()捕獲。否則為None。
在 3.5 版更改: 添加了 stdout 和 stderr 屬性。
-
常用參數?
為了支持豐富的使用案例, Popen 的構造函數(以及方便的函數)接受大量可選的參數。對于大多數典型的用例,許多參數可以被安全地留以它們的默認值。通常需要的參數有:
args 被所有調用需要,應當為一個字符串,或者一個程序參數序列。提供一個參數序列通常更好,它可以更小心地使用參數中的轉義字符以及引用(例如允許文件名中的空格)。如果傳遞一個簡單的字符串,則 shell 參數必須為
True(見下文)或者該字符串中將被運行的程序名必須用簡單的命名而不指定任何參數。stdin, stdout 和 stderr 分別指定了執行的程序的標準輸入、輸出和標準錯誤文件句柄。合法的值有
PIPE、DEVNULL、 一個現存的文件描述符(一個正整數)、一個現存的文件對象以及None。PIPE表示應該新建一個對子進程的管道。DEVNULL表示使用特殊的文件os.devnull。當使用默認設置None時,將不會進行重定向,子進程的文件流將繼承自父進程。另外, stderr 可能為STDOUT,表示來自于子進程的標準錯誤數據應該被 stdout 相同的句柄捕獲。如果 encoding 或 errors 被指定,或者 text (也名為 universal_newlines)為真,則文件對象 stdin 、 stdout 與 stderr 將會使用在此次調用中指定的 encoding 和 errors 以文本模式打開或者為默認的
io.TextIOWrapper。當構造函數的 newline 參數為
None時。對于 stdin, 輸入的換行符'\n'將被轉換為默認的換行符os.linesep。對于 stdout 和 stderr, 所有輸出的換行符都被轉換為'\n'。更多信息,查看io.TextIOWrapper類的文檔。如果文本模式未被使用, stdin, stdout 和 stderr 將會以二進制流模式打開。沒有編碼與換行符轉換發生。
3.6 新版功能: 添加了 encoding 和 errors 形參。
3.7 新版功能: 添加了 text 形參作為 universal_newlines 的別名。
注解
文件對象
Popen.stdin、Popen.stdout和Popen.stderr的換行符屬性不會被Popen.communicate()方法更新。如果 shell 設為
True,,則使用 shell 執行指定的指令。如果您主要使用 Python 增強的控制流(它比大多數系統 shell 提供的強大),并且仍然希望方便地使用其他 shell 功能,如 shell 管道、文件通配符、環境變量展開以及~展開到用戶家目錄,這將非常有用。但是,注意 Python 自己也實現了許多類似 shell 的特性(例如glob,fnmatch,os.walk(),os.path.expandvars(),os.path.expanduser()和shutil)。在 3.3 版更改: 當 universal_newline 被設為
True,則類使用locale.getpreferredencoding(False)編碼來代替locale.getpreferredencoding()。關于它們的區別的更多信息,見io.TextIOWrapper。注解
在使用
shell=True之前, 請閱讀 Security Considerations 段落。
這些選項以及所有其他選項在 Popen 構造函數文檔中有更詳細的描述。
Popen 構造函數?
此模塊的底層的進程創建與管理由 Popen 類處理。它提供了很大的靈活性,因此開發者能夠處理未被便利函數覆蓋的不常見用例。
-
class
subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None)? 在一個新的進程中執行子程序。在 POSIX,此類使用類似于
os.execvp()的行為來執行子程序。在 Windows,此類使用了 WindowsCreateProcess()函數。Popen的參數如下:args 應當是一個程序的參數列表或者一個簡單的字符串。默認情況下,如果 args 是一個序列,將運行的程序是此序列的第一項。如果 args 是一個字符串,解釋是平臺相關的,如下所述。有關默認行為的其他差異,見 shell 和 executable 參數。除非另有說明,推薦將 args 作為序列傳遞。
向外部函數傳入序列形式參數的一個例子如下:
Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
在 POSIX,如果 args 是一個字符串,此字符串被作為將被執行的程序的命名或路徑解釋。但是,只有在不傳遞任何參數給程序的情況下才能這么做。
注解
將 shell 命令拆分為參數序列的方式可能并不很直觀,特別是在復雜的情況下。
shlex.split()可以演示如何確定 args 適當的拆分形式:>>> import shlex, subprocess >>> command_line = input() /bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'" >>> args = shlex.split(command_line) >>> print(args) ['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"] >>> p = subprocess.Popen(args) # Success!
特別注意,由 shell 中的空格分隔的選項(例如 -input)和參數(例如 eggs.txt )位于分開的列表元素中,而在需要時使用引號或反斜杠轉義的參數在 shell (例如包含空格的文件名或上面顯示的 echo 命令)是單獨的列表元素。
在 Windows,如果 args 是一個序列,他將通過一個在 在 Windows 上將參數列表轉換為一個字符串 描述的方式被轉換為一個字符串。這是因為底層的
CreateProcess()只處理字符串。參數 shell (默認為
False)指定是否使用 shell 執行程序。如果 shell 為True,更推薦將 args 作為字符串傳遞而非序列。在 POSIX,當
shell=True, shell 默認為/bin/sh。如果 args 是一個字符串,此字符串指定將通過 shell 執行的命令。這意味著字符串的格式必須和在命令提示符中所輸入的完全相同。這包括,例如,引號和反斜杠轉義包含空格的文件名。如果 args 是一個序列,第一項指定了命令,另外的項目將作為傳遞給 shell (而非命令) 的參數對待。也就是說,Popen等同于:Popen(['/bin/sh', '-c', args[0], args[1], ...])
在 Windows,使用
shell=True,環境變量COMSPEC指定了默認 shell。在 Windows 你唯一需要指定shell=True的情況是你想要執行內置在 shell 中的命令(例如 dir 或者 copy)。在運行一個批處理文件或者基于控制臺的可執行文件時,不需要shell=True。注解
在使用
shell=True之前, 請閱讀 Security Considerations 段落。bufsize 將在
open()函數創建了 stdin/stdout/stderr 管道文件對象時作為對應的參數供應:0表示不使用緩沖區 (讀取與寫入是一個系統調用并且可以返回短內容)1表示行緩沖(只有universal_newlines=True時才有用,例如,在文本模式中)任何其他正值表示使用一個約為對應大小的緩沖區
負的 bufsize (默認)表示使用系統默認的 io.DEFAULT_BUFFER_SIZE。
在 3.3.1 版更改: bufsize 現在默認為 -1 來啟用緩沖,以符合大多數代碼所期望的行為。在 Python 3.2.4 和 3.3.1 之前的版本中,它錯誤地將默認值設為了為
0,這是無緩沖的并且允許短讀取。這是無意的,并且與大多數代碼所期望的 Python 2 的行為不一致。executable 參數指定一個要執行的替換程序。這很少需要。當
shell=True, executable 替換 args 指定運行的程序。但是,原始的 args 仍然被傳遞給程序。大多數程序將被 args 指定的程序作為命令名對待,這可以與實際運行的程序不同。在 POSIX, args 名作為實際調用程序中可執行文件的顯示名稱,例如 ps。如果shell=True,在 POSIX, executable 參數指定用于替換默認 shell/bin/sh的 shell。stdin, stdout 和 stderr 分別指定被運行的程序的標準輸入、輸出和標準錯誤的文件句柄。合法的值有
PIPE,DEVNULL, 一個存在的文件描述符(一個正整數),一個存在的 文件對象 以及None。PIPE表示應創建一個新的對子進程的管道。DEVNULL表示使用特殊的os.devnull文件。使用默認的None,則不進行成定向;子進程的文件流將繼承自父進程。另外, stderr 可設為STDOUT,表示應用程序的標準錯誤數據應和標準輸出一同捕獲。如果 preexec_fn 被設為一個可調用對象,此對象將在子進程剛創建時被調用。(僅 POSIX)
警告
preexec_fn 形參在應用程序中存在多線程時是不安全的。子進程在調用前可能死鎖。如果你必須使用它,保持警惕!最小化你調用的庫的數量。
注解
如果你需要修改子進程環境,使用 env 形參而非在 preexec_fn 中進行。 start_new_session 形參可以代替之前常用的 preexec_fn 來在子進程中調用 os.setsid()。
如果 close_fds 為真,所有文件描述符除了
0,1,2之外都會在子進程執行前關閉。而當 close_fds 為假時,文件描述符遵守它們繼承的標志,如 文件描述符的繼承 所述。在 Windows,如果 close_fds 為真, 則子進程不會繼承任何句柄,除非在
STARTUPINFO.IpAttributeList的handle_list的鍵中顯式傳遞,或者通過標準句柄重定向傳遞。在 3.2 版更改: close_fds 的默認值已經從
False修改為上述值。在 3.7 版更改: 在 Windows,當重定向標準句柄時 close_fds 的默認值從
False變為True。現在重定向標準句柄時有可能設置 close_fds 為True。(標準句柄指三個 stdio 的句柄)pass_fds 是一個可選的在父子進程間保持打開的文件描述符序列。提供任何 pass_fds 將強制 close_fds 為
True。(僅 POSIX)3.2 新版功能: 加入了 pass_fds 形參。
如果 cwd 不為
None,此函數在執行子進程前改變當前工作目錄為 cwd。 cwd 可以為一個str和 path-like 對象。特別要注意,當可執行文件的路徑為相對路徑時,此函數按相對于 cwd 的路徑來尋找 executable (或者 args 的第一項)。在 3.6 版更改: cwd 形參接受一個 path-like object。
?如果 restore_signals 為 true(默認值),則 Python 設置為 SIG_IGN 的所有信號將在 exec 之前的子進程中恢復為 SIG_DFL。目前,這包括 SIGPIPE ,SIGXFZ 和 SIGXFSZ 信號。 (僅 POSIX)
在 3.2 版更改: restore_signals 被加入。
如果 start_new_session 為 true,則 setsid() 系統調用將在子進程執行之前被執行。(僅 POSIX)
在 3.2 版更改: start_new_session 被添加。
如果 env 不為
None,則必須為一個為新進程定義了環境變量的字典;這些用于替換繼承的當前進程環境的默認行為。注解
如果指定, env 必須提供所有被子進程需求的變量。在 Windows,為了運行一個 side-by-side assembly ,指定的 env 必須 包含一個有效的
SystemRoot。如果 encoding 或 errors 被指定,或者 text 為 true,則文件對象 stdin, stdout 和 stderr 將會以指定的編碼和 errors 以文本模式打開,如同 常用參數 所述。 universal_newlines 參數等同于 text 并且提供向后兼容性。默認情況下,文件對象都以二進制模式打開。
3.6 新版功能: encoding 和 errors 被添加。
3.7 新版功能: text 作為 universal_newlines 的一個更具可讀性的別名被添加。
如果給出, startupinfo 將是一個將被傳遞給底層的
CreateProcess函數的STARTUPINFO對象。 creationflags,如果給出,可以是一個或多個以下標志之一:Popen 對象支持通過
with語句作為上下文管理器,在退出時關閉文件描述符并等待進程:with Popen(["ifconfig"], stdout=PIPE) as proc: log.write(proc.stdout.read())
在 3.2 版更改: 添加了上下文管理器支持。
在 3.6 版更改: 現在,如果 Popen 析構時子進程仍然在運行,則析構器會發送一個
ResourceWarning警告。
異常?
在子進程中拋出的異常,在新的進程開始執行前,將會被再次在父進程中拋出。
最常見的被拋出異常是 OSError。例如,當嘗試執行一個不存在的文件時就會發生。應用程序需要為 OSError 異常做好準備。
如果 Popen 調用時有無效的參數,則一個 ValueError 將被拋出。
check_call() 與 check_output() 在調用的進程返回非零退出碼時將拋出 CalledProcessError。
所有接受 timeout 形參的函數與方法,例如 call() 和 Popen.communicate() 將會在進程退出前超時到期時拋出 TimeoutExpired。
此模塊中定義的異常都繼承自 SubprocessError。
3.3 新版功能: 基類
SubprocessError被添加。
安全考量?
不像一些其他的 popen 功能,此實現絕不會隱式調用一個系統 shell。這意味著任何字符,包括 shell 元字符,可以安全地被傳遞給子進程。如果 shell 被明確地調用,通過 shell=True 設置,則確保所有空白字符和元字符被恰當地包裹在引號內以避免 shell 注入 漏洞就由應用程序負責了。
當使用 shell=True, shlex.quote() 函數可以作為在將被用于構造 shell 指令的字符串中轉義空白字符以及 shell 元字符的方案。
Popen 對象?
Popen 類的實例擁有以下方法:
-
Popen.poll()? 檢查子進程是否已被終止。設置并返回
returncode屬性。否則返回None。
-
Popen.wait(timeout=None)? 等待子進程被終止。設置并返回
returncode屬性。如果進程在 timeout 秒后未中斷,拋出一個
TimeoutExpired異常,可以安全地捕獲此異常并重新等待。注解
當
stdout=PIPE或者stderr=PIPE并且子進程產生了足以阻塞 OS 管道緩沖區接收更多數據的輸出到管道時,將會發生死鎖。當使用管道時用Popen.communicate()來規避它。注解
此函數使用了一個 busy loop (非阻塞調用以及短睡眠) 實現。使用
asyncio模塊進行異步等待: 參閱asyncio.create_subprocess_exec。在 3.3 版更改: timeout 被添加
-
Popen.communicate(input=None, timeout=None)? 與進程交互:向 stdin 傳輸數據。從 stdout 和 stderr 讀取數據,直到文件結束符。等待進程終止。可選的 input 參數應當未被傳輸給子進程的數據,如果沒有數據應被傳輸給子進程則為
None。如果流以文本模式打開, input 必須為字符串。否則,它必須為字節。communicate()返回一個(stdout_data, stderr_data)元組。如果文件以文本模式打開則為字符串;否則字節。注意如果你想要向進程的 stdin 傳輸數據,你需要通過
stdin=PIPE創建此 Popen 對象。類似的,要從結果元組獲取任何非None值,你同樣需要設置stdout=PIPE或者stderr=PIPE。如果進程在 timeout 秒后未終止,一個
TimeoutExpired異常將被拋出。捕獲此異常并重新等待將不會丟失任何輸出。如果超時到期,子進程不會被殺死,所以為了正確清理一個行為良好的應用程序應該殺死子進程并完成通訊。
proc = subprocess.Popen(...) try: outs, errs = proc.communicate(timeout=15) except TimeoutExpired: proc.kill() outs, errs = proc.communicate()
注解
內存里數據讀取是緩沖的,所以如果數據尺寸過大或無限,不要使用此方法。
在 3.3 版更改: timeout 被添加
-
Popen.send_signal(signal)? 將信號 signal 發送給子進程。
注解
在 Windows, SIGTERM 是一個
terminate()的別名。 CTRL_C_EVENT 和 CTRL_BREAK_EVENT 可以被發送給以包含CREATE_NEW_PROCESS的 creationflags 形參啟動的進程。
-
Popen.terminate()? 停止下級進程。 在 POSIX 操作系統上,此方法會發送 SIGTERM 給下級進程。 在 Windows 上則會調用 Win32 API 函數
TerminateProcess()來停止下級進程。
-
Popen.kill()? 殺死子進程。 在 POSIX 操作系統上,此函數會發送 SIGKILL 給子進程。 在 Windows 上
kill()則是terminate()的別名。
以下屬性也是可用的:
-
Popen.stdin? 如果 stdin 參數為
PIPE,此屬性是一個類似open()返回的可寫的流對象。如果 encoding 或 errors 參數被指定或者 universal_newlines 參數為True,則此流是一個文本流,否則是字節流。如果 stdin 參數非PIPE, 此屬性為None。
-
Popen.stdout? 如果 stdout 參數是
PIPE,此屬性是一個類似open()返回的可讀流。從流中讀取子進程提供的輸出。如果 encoding 或 errors 參數被指定或者 universal_newlines 參數為True,此流為文本流,否則為字節流。如果 stdout 參數非PIPE,此屬性為None。
-
Popen.stderr? 如果 stderr 參數是
PIPE,此屬性是一個類似open()返回的可讀流。從流中讀取子進程提供的輸出。如果 encoding 或 errors 參數被指定或者 universal_newlines 參數為True,此流為文本流,否則為字節流。如果 stderr 參數非PIPE,此屬性為None。
警告
使用 communicate() 而非 .stdin.write, .stdout.read 或者 .stderr.read 來避免由于任意其他 OS 管道緩沖區被子進程填滿阻塞而導致的死鎖。
-
Popen.pid? 子進程的進程號。
注意如果你設置了 shell 參數為
True,則這是生成的子 shell 的進程號。
-
Popen.returncode? 此進程的退出碼,由
poll()和wait()設置(以及直接由communicate()設置)。一個None值 表示此進程仍未結束。一個負值
-N表示子進程被信號N中斷 (僅 POSIX).
Windows Popen 助手?
STARTUPINFO 類和以下常數僅在 Windows 有效。
-
class
subprocess.STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, hStdError=None, wShowWindow=0, lpAttributeList=None)? 在
Popen創建時部分支持 Windows 的 STARTUPINFO 結構。接下來的屬性僅能通過關鍵詞參數設置。在 3.7 版更改: 僅關鍵詞參數支持被加入。
-
dwFlags? 一個位字段,用于確定進程在創建窗口時是否使用某些
STARTUPINFO屬性。si = subprocess.STARTUPINFO() si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
-
hStdInput? 如果
dwFlags被指定為STARTF_USESTDHANDLES,則此屬性是進程的標準輸入句柄,如果STARTF_USESTDHANDLES未指定,則默認的標準輸入是鍵盤緩沖區。
-
hStdOutput? 如果
dwFlags被指定為STARTF_USESTDHANDLES,則此屬性是進程的標準輸出句柄。除此之外,此此屬性將被忽略并且默認標準輸出是控制臺窗口緩沖區。
-
hStdError? 如果
dwFlags被指定為STARTF_USESTDHANDLES,則此屬性是進程的標準錯誤句柄。除此之外,此屬性將被忽略并且默認標準錯誤為控制臺窗口的緩沖區。
-
wShowWindow? 如果
dwFlags指定了STARTF_USESHOWWINDOW,此屬性可為能被指定為 函數 ShowWindow 的nCmdShow 的形參的任意值,除了SW_SHOWDEFAULT。如此之外,此屬性被忽略。
-
lpAttributeList? STARTUPINFOEX給出的用于進程創建的額外屬性字典,參閱 UpdateProcThreadAttribute。支持的屬性:
- handle_list
將被繼承的句柄的序列。如果非空, close_fds 必須為 true。
當傳遞給
Popen構造函數時,這些句柄必須暫時地能被os.set_handle_inheritable()繼承,否則OSError將以 Windows errorERROR_INVALID_PARAMETER(87) 拋出。警告
在多線程進程中,請謹慎使用,以便在將此功能與對繼承所有句柄的其他進程創建函數——例如
os.system()的并發調用——相結合時,避免泄漏標記為可繼承的句柄。這也應用于臨時性創建可繼承句柄的標準句柄重定向。
3.7 新版功能.
-
Windows 常數?
subprocess 模塊曝出以下常數。
-
subprocess.STD_INPUT_HANDLE? 標準輸入設備,這是控制臺輸入緩沖區
CONIN$。
-
subprocess.STD_OUTPUT_HANDLE? 標準輸出設備。最初,這是活動控制臺屏幕緩沖區
CONOUT$。
-
subprocess.STD_ERROR_HANDLE? 標準錯誤設備。最初,這是活動控制臺屏幕緩沖區
CONOUT$。
-
subprocess.SW_HIDE? 隱藏窗口。另一個窗口將被激活。
-
subprocess.STARTF_USESTDHANDLES? 指明
STARTUPINFO.hStdInput,STARTUPINFO.hStdOutput和STARTUPINFO.hStdError屬性包含額外的信息。
-
subprocess.STARTF_USESHOWWINDOW? 指明
STARTUPINFO.wShowWindow屬性包含額外的信息。
-
subprocess.CREATE_NEW_CONSOLE? 新的進程將有新的控制臺,而不是繼承父進程的(默認)控制臺。
-
subprocess.CREATE_NEW_PROCESS_GROUP? Popencreationflags形參用于指明將創建一個新的進程組。 這個旗標對于在子進程上使用os.kill()來說是必須的。如果指定了
CREATE_NEW_CONSOLE則這個旗標會被忽略。
-
subprocess.REALTIME_PRIORITY_CLASS? 用于指明一個新進程將具有實時優先級的
Popencreationflags形參。 你應當幾乎永遠不使用 REALTIME_PRIORITY_CLASS,因為這會中斷管理鼠標輸入、鍵盤輸入以及后臺磁盤刷新的系統線程。 這個類只適用于直接與硬件“對話”,或者執行短暫任務具有受限中斷的應用。3.7 新版功能.
-
subprocess.DETACHED_PROCESS? 指明一個新進程將不會繼承其父控制臺的
Popencreationflags形參。 這個值不能與 CREATE_NEW_CONSOLE 一同使用。3.7 新版功能.
較舊的高階 API?
在 Python 3.5 之前,這三個函數組成了 subprocess 的高階 API。 現在你可以在許多情況下使用 run(),但有大量現在代碼仍會調用這些函數。
-
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)? 運行由 args 所描述的命令。 等待命令完成,然后返回
returncode屬性。Code needing to capture stdout or stderr should use
run()instead:run(...).returncode
要屏蔽 stdout 或 stderr,可提供
DEVNULL這個值。上面顯示的參數只是常見的一些。 完整的函數簽名與
Popen構造器的相同 —— 此函數會將所提供的 timeout 之外的全部參數直接傳遞給目標接口。注解
請不要在此函數中使用
stdout=PIPE或stderr=PIPE。 如果子進程向管道生成了足以填滿 OS 管理緩沖區的輸出而管道還未被讀取時它將會阻塞。在 3.3 版更改: timeout 被添加
-
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)? 附帶參數運行命令。 等待命令完成。 如果返回碼為零則正常返回,否則引發
CalledProcessError。CalledProcessError對象將在returncode屬性中保存返回碼。Code needing to capture stdout or stderr should use
run()instead:run(..., check=True)
要屏蔽 stdout 或 stderr,可提供
DEVNULL這個值。上面顯示的參數只是常見的一些。 完整的函數簽名與
Popen構造器的相同 —— 此函數會將所提供的 timeout 之外的全部參數直接傳遞給目標接口。注解
請不要在此函數中使用
stdout=PIPE或stderr=PIPE。 如果子進程向管道生成了足以填滿 OS 管理緩沖區的輸出而管道還未被讀取時它將會阻塞。在 3.3 版更改: timeout 被添加
-
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)? 附帶參數運行命令并返回其輸出。
如果返回碼非零則會引發
CalledProcessError。CalledProcessError對象將在returncode屬性中保存返回碼并在output屬性中保存所有輸出。這相當于:
run(..., check=True, stdout=PIPE).stdout
上面顯示的參數只是常見的一些。 完整的函數簽名與
run()的大致相同 —— 大部分參數會被直接傳遞給目標接口。 但是,顯式地傳遞input=None來繼承父對象的標準輸入文件處理的特性則不受支持。默認情況下,此函數將把數據返回為已編碼的字節串。 輸出數據的實際編碼格式將取決于發起調用的命令,因此解碼為文本的操作往往需要在應用程序層級上進行處理。
此行為可以通過設置 text, encoding, errors 或將 universal_newlines 設為
True來重載,具體描述見 常用參數 和run()。要在結果中同時捕獲標準錯誤,請使用
stderr=subprocess.STDOUT:>>> subprocess.check_output( ... "ls non_existent_file; exit 0", ... stderr=subprocess.STDOUT, ... shell=True) 'ls: non_existent_file: No such file or directory\n'
3.1 新版功能.
在 3.3 版更改: timeout 被添加
在 3.4 版更改: 增加了對 input 關鍵字參數的支持。
在 3.6 版更改: 增加了 encoding 和 errors。 詳情參見
run()。3.7 新版功能: text 作為 universal_newlines 的一個更具可讀性的別名被添加。
使用 subprocess 模塊替換舊函數?
在這一節中,"a 改為 b" 意味著 b 可以被用作 a 的替代。
注解
在這一節中的所有 "a" 函數會在找不到被執行的程序時(差不多)靜默地失敗;"b" 替代則會改為引發 OSError。
此外,在使用 check_output() 時如果替代函數所請求的操作產生了非零返回值則將失敗并引發 CalledProcessError。 操作的輸出仍能以所引發異常的 output 屬性的方式被訪問。
在下列例子中,我們假定相關的函數都已從 subprocess 模塊中導入了。
Replacing /bin/sh shell backquote?
output=`mycmd myarg`
改為:
output = check_output(["mycmd", "myarg"])
替代 shell 管道?
output=`dmesg | grep hda`
改為:
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
The p1.stdout.close() call after starting the p2 is important in order for p1 to receive a SIGPIPE if p2 exits before p1.
另外,對于受信任的輸入,shell 本身的管道支持仍然可被直接使用:
output=`dmesg | grep hda`
改為:
output=check_output("dmesg | grep hda", shell=True)
替代 os.system()?
sts = os.system("mycmd" + " myarg")
# becomes
sts = call("mycmd" + " myarg", shell=True)
注釋:
通過 shell 來調用程序通常是不必要的。
一個更現實的例子如下所示:
try:
retcode = call("mycmd" + " myarg", shell=True)
if retcode < 0:
print("Child was terminated by signal", -retcode, file=sys.stderr)
else:
print("Child returned", retcode, file=sys.stderr)
except OSError as e:
print("Execution failed:", e, file=sys.stderr)
替代 os.spawn 函數族?
P_NOWAIT 示例:
pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid
P_WAIT 示例:
retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])
Vector 示例:
os.spawnvp(os.P_NOWAIT, path, args)
==>
Popen([path] + args[1:])
Environment 示例:
os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
==>
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
替代 os.popen(), os.popen2(), os.popen3()?
(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
(child_stdin,
child_stdout,
child_stderr) = os.popen3(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
(child_stdin,
child_stdout,
child_stderr) = (p.stdin, p.stdout, p.stderr)
(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)
返回碼以如下方式處理轉寫:
pipe = os.popen(cmd, 'w')
...
rc = pipe.close()
if rc is not None and rc >> 8:
print("There were some errors")
==>
process = Popen(cmd, stdin=PIPE)
...
process.stdin.close()
if process.wait() != 0:
print("There were some errors")
來自 popen2 模塊的替代函數?
注解
如果 popen2 函數的 cmd 參數是一個字符串,命令會通過 /bin/sh 來執行。 如果是一個列表,命令會被直接執行。
(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
==>
p = Popen("somestring", shell=True, bufsize=bufsize,
stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin
(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
==>
p = Popen(["mycmd", "myarg"], bufsize=bufsize,
stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)
popen2.Popen3 和 popen2.Popen4 基本上類似于 subprocess.Popen,不同之處在于:
舊式的 Shell 發起函數?
此模塊還提供了以下來自 2.x commands 模塊的舊版函數。 這些操作會隱式地發起調用系統 shell 并且上文所描述的有關安全與異常處理一致性保證都不適用于這些函數。
-
subprocess.getstatusoutput(cmd)? 返回在 shell 中執行 cmd 產生的
(exitcode, output)。在 shell 中以
Popen.check_output()執行字符串 cmd 并返回一個 2 元組(exitcode, output)。 會使用當前區域設置的編碼格式;請參閱 常用參數 中的說明來了解詳情。末尾的一個換行符會從輸出中被去除。 命令的退出碼可被解讀為子進程的返回碼。 例如:
>>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') >>> subprocess.getstatusoutput('cat /bin/junk') (1, 'cat: /bin/junk: No such file or directory') >>> subprocess.getstatusoutput('/bin/junk') (127, 'sh: /bin/junk: not found') >>> subprocess.getstatusoutput('/bin/kill $$') (-15, '')
可用性: POSIX 和 Windows。
在 3.3.4 版更改: 添加了 Windows 支持。
此函數現在返回 (exitcode, output) 而不是像 Python 3.3.3 及更早的版本那樣返回 (status, output)。 exitcode 的值與
returncode相同。
-
subprocess.getoutput(cmd)? 返回在 shell 中執行 cmd 產生的輸出(stdout 和 stderr)。
類似于
getstatusoutput(),但退出碼會被忽略并且返回值為包含命令輸出的字符串。 例如:>>> subprocess.getoutput('ls /bin/ls') '/bin/ls'
可用性: POSIX 和 Windows。
在 3.3.4 版更改: 添加了 Windows 支持
注釋?
在 Windows 上將參數列表轉換為一個字符串?
在 Windows 上,args 序列會被轉換為可使用以下規則來解析的字符串(對應于 MS C 運行時所使用的規則):
參數以空白符分隔,即空格符或制表符。
用雙引號標示的字符串會被解讀為單個參數,而不再考慮其中的空白符。 一個參數可以嵌套用引號標示的字符串。
帶有一個反斜杠前綴的雙引號會被解讀為雙引號字面值。
反斜杠會按字面值解讀,除非它是作為雙引號的前綴。
如果反斜杠被作為雙引號的前綴,則每個反斜杠對會被解讀為一個反斜杠字面值。 如果反斜杠數量為奇數,則最后一個反斜杠會如規則 3 所描述的那樣轉義下一個雙引號。
參見
shlex此模塊提供了用于解析和轉義命令行的函數。
