subprocess 模組最重要的是 Popen 類別,建立 Popen 物件時將會新增子行程去執行你要的工作,Popen 類別用起來比較精細,可操作的地方較多,相對較麻煩一些。因此 subprocess 模組提供下列三種方便的函式來新增子行程,注意到這三個函式是屬於同步呼叫 (synchronous call) 的方式,一定會等到子行程結束才執行下一行程式碼。
- subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
最簡單的子行程新增方式,執行並等待結束,回傳子行程的回傳值 (return code)。 - subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
呼叫子行程,並判斷回傳值是否為是否為 0,不然就引發 CalledProcessError 例外。 - subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
呼叫子行程,與 subprocess.check_call 函式行為相似,但回傳 stdout 的字串值。
class subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
Popen 物件則有下列方法和屬性:
- 方法
- Popen.poll():判斷子行程是否結束,如果結束回傳 returncode 值,否則回傳 None 。
- Popen.wait():等待子行程結束,回傳 returncode 值。
- Popen.communicate(input=None):與子行程通訊,回傳 tuple 資料型態為 (stdoutdata, stderrdata),注意要通訊的 stdin, stdout, stderr 引數必須設定為 subprocess.PIPE 。
- Popen.send_signal(signal):送信號給子行程。
- Popen.terminate():終止子行程,送出 SIGTERM 信號。
- Popen.kill():停止子行程,送出 SIGKILL 信號。
- 屬性
- stdin:如果建立 Popen 時的 stdin 引數是 subprocess.PIPE,那麼這個屬性會是 file object,否則為 None。
- stdout:如果建立 Popen 時的 stdout 引數是 subprocess.PIPE,那麼這個屬性會是 file object,否則為 None。
- stderr:如果建立 Popen 時的 stderr 引數是 subprocess.PIPE,那麼這個屬性會是 file object,否則為 None。
- pid:子行程的 process ID。
- returncode:子行程結束的回傳值,如果子行程還在執行沒有結束,returncode 會是 None 。
import subprocess subprocess.check_output(['printf','Hello World\n']) subprocess.check_output(['printf "Hello World\n"'], shell=True) subprocess.check_output('printf "Hello World\n"', shell=True)
上述 3 行程式碼執行結果是相同的,差別在於 shell=True 時必須用引號處理空白和 metacharacters,最後一行則是因為序列 (sequence) 的引數只有一個,可以簡化成字串作為引數。
文件中建議,如果讓使用者輸入參數作為子行程的引數會有安全行的問題,容易發生 Shell injection 的危險,如果你很確定引數沒有任何疑慮,使用 shell=True 倒是讓程式碼更容易閱讀。
###
沒有留言:
張貼留言