subprocess中命令為參數序列和字符串的區別

參數args

參數args可以是一個參數序列,也可以是一個單獨的字符串。參數序列通常是首選的,因為它允許模塊處理參數的轉義和引號(例如,允許文件名中有空格)。

如果傳遞參數序列,默認情況下,程序執行序列的第一個元素,後面所有的元素都作為參數。

如果傳一個單獨字符串,要麼參數shell為True,要麼字符串必須沒有指定任何參數的可執行程序的名稱。

所以,一般的搭配是參數序列和shell=False,字符串和shell=True

參數shell

shell參數設置是否在單獨的shell中執行命令。如果shell=True,則是派生一個新的shell來解釋執行命令。如果你使用Python主要是為了增強它在大多數系統shell上提供的控制流,並且還想方便的訪問shell特性,如shell的管道符、文件通配符、環境變量擴展或者~擴展到home目錄等,這個參數將非常有用。

不同平台下shell參數使用

shell=False
對於Unix平台,如果args是字符串,這個字符串將被解釋為程序的名稱或路徑,然後被執行。然而,這僅僅只有在不給這個程序傳遞任何參數時才能被執行。

import subprocess
subprocess.Popen('ls', shell=False)  # get the result
subprocess.Popen('ls', shell=False)  # raise Exception: FileNotFoundError

對於windows平台,如果args是個序列,它將被轉換成一個字符串通過以下方式:Converting an argument swquence to a string on Windows ,這是因為底層的CreateProcess()只能操作字符串。

shell=True

在Unix平台下shell=True,shell默認為/bin/sh。如果args是字符串,通過shell執行字符串指定的命令。這意味着字符串的格式必須與在shell提示符下鍵入時的格式完全相同。例如, 使用引號或反斜杠轉義包含空格的文件名。如果args是一個序列,第一個元素指定了命令字符串,其它的元素他的參數。

在Windows平台下shell=True,環境變量COMSPEC指定了默認的shell。只有當你想要執行的命令內置於shell中時,你才需要指定shell=True(例如dircopy)。運行批處理文件或基於控制台的可執行文件不需要shell=True

args的參數序列和字符串的區別

這裡的字符串指的是shell=True下的字符串

  • 使用序列不需要派生一個新的shell解釋器。所以比字符串更快一點
  • 使用shell參數容易引起shell注入漏洞,使用shlex.quote() 函數可以正確轉義空格和shell命令中的元字符

參考

Tags: