2015-06-16 85 views
0

當使用subprocess.Popen,我們不得不寫的爲什麼我們不能在subprocess.Popen中結合參數?

with subprocess.Popen(['ls', '-l', '-a'], stdout=subprocess.PIPE) as proc: 
    print(proc.stdout.read()) 

代替

with subprocess.Popen(['ls', '-l -a'], stdout=subprocess.PIPE) as proc: 
    print(proc.stdout.read()) 

爲什麼? ls會在第二種情況下得到什麼?謝謝。

+3

您不能運行'LS「在shell -l -a''無論是。嘗試一下。 –

回答

1

在第二種情況下,作爲單個字符串的-l -a將成爲ls的第一個參數,它不知道該如何處理,或者至少不會做你想做的事情。在第一種情況下,-l是第一個參數,-a是第二個參數。

如果你想建立一個具有完整的命令,你可以使用shell=True標誌POPEN,而是一個字符串,您的命令將"ls -l -a"['ls', '-l -a']

隨着Popen列表中的每個參數傳遞給一個說法該命令正在執行,它不是一個傳遞給被解釋的shell的字符串,除非你要求將它傳遞給shell來解釋。

+0

......而且,很明顯,當使用'shell = True'時,字符串'「ls -l -a」'將被改變成一個argv數組'''ls','-l',' - '一個']'由該外殼。 –

3

當你的操作系統啓動一個可執行文件,它通過一個電話的東西非常喜歡這樣做的:

execv('/usr/bin/ls', 'ls', '-l', '-a', NULL) 

注意,參數已經拆分爲三個獨立的話ls開始前;如果你正在用shell運行你的程序,那麼shell會負責分離;如果您通過一種編程語言來運行它,那麼您可以直接控制調用的參數,然後您就可以決定如何自行拆分數組。

ls運行,所以通過這些參數在數組中,argv。見證通常的方式一個main函數是以C聲明:

int main(int argc, char *argv[]) { 
    ... 
} 

它越來越論點的陣列,在常規命名爲argv變量,已經分解成單個的單詞。

ls解析器,那麼,可以預期,它的運行時,將交由一個數組,看起來像這樣:

argc = 3     # three arguments, including our own name 
argv = ['ls', '-l', '-a'] # first argument is our name, others follow 

...所以內置ls命令行解析器不在ls命令啓動之前,需要分解其參數中的空格 - 空格已經被刪除,並且語法引用被優先和剝離。

現在,當您運行['ls', '-l -a']時,您明確指定了一個2而不是3的argc和一個包含單個字符串-l -a的單個參數。要獲得從shell這種行爲,你需要使用引用或轉義:

ls "-l -a" 
ls '-l -a' 
ls -l\ -a 

...你會發現,從外殼調用時ls失敗的確切方式,你在這裏買到相同與任何這些用法。

+0

注:在Windows上,這是一個[不同的故事](http://www.daviddeley.com/autohotkey/parameters/parameters.htm) – jfs

+0

@JFSebastian,我之前是一個更開心的人該鏈接。編譯器特定的argv程序集? Ewwww! –

0

如果要使用命令的字符串表示來執行,shlex模塊可能會有用。

shlex.split(S [評論[,POSIX]])

分割字符串s使用殼狀的語法。如果註釋爲False(缺省值),則解析給定字符串中的註釋將爲 已禁用(將shlex實例的commenters屬性設置爲 空字符串)。此功能默認以POSIX模式運行, ,但如果posix參數爲false,則使用非POSIX模式。

assert shlex.split("ls -a -l") == ['ls', '-a', '-l'] 
subprocess.Popen(shlex.split("ls -a -l")) 

它還涉及更復雜的情況比如逃逸字符或引用用法:

assert shlex.split("cat 'file with space.txt'") == ['cat', 'file with space.txt'] 
assert shlex.split(r"cat file\ with\ space.txt") == ['cat', 'file with space.txt'] 
相關問題