2014-10-17 28 views
1

我試圖讓python的subprocess.call方法通過列表(由一系列字符串)接受一些args命令,正如在python文檔中所建議的。爲了把它變成我的實際腳本之前探討這個問題,我打開了IPython中,跑出涉及的shell設置和args命令的不同組合一些命令,並得到了以下行爲:當使用shell = True時忽略subprocess.call()參數w/list

In [3]: subprocess.call(['ls', '-%sl' %'a']) 
total 320 
drwxr-xr-x 20 Kohaugustine staff 680 Oct 15 16:55 . 
drwxr-xr-x 5 Kohaugustine staff 170 Sep 12 17:16 .. 
-rwxr-xr-x 1 Kohaugustine staff 8544 Oct 15 16:55 a.out 
-rwxr-xr-x 1 Kohaugustine staff 8544 Oct 3 10:28 ex1-6 
[email protected] 1 Kohaugustine staff 204 Oct 3 10:28 ex1-6.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Oct 3 10:15 ex1-7 
[email protected] 1 Kohaugustine staff 71 Oct 3 10:15 ex1-7.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:22 hello 
[email protected] 1 Kohaugustine staff 58 Sep 12 16:27 hello.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:24 hello.o 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:24 hello_1.o 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:27 hello_2.o 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:27 hello_3.o 
-rwxr-xr-x 1 Kohaugustine staff 8544 Oct 15 16:55 lesson_1-5 
[email protected] 1 Kohaugustine staff 185 Sep 28 10:35 lesson_1-5.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 21 10:06 temperature.o 
[email protected] 1 Kohaugustine staff 406 Sep 21 09:54 temperature_ex1-3.c 
[email protected] 1 Kohaugustine staff 582 Sep 21 10:06 temperature_ex1-4.c 
[email protected] 1 Kohaugustine staff 178 Sep 23 17:21 temperature_ex1-5.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 23 17:21 temperature_ex1-5.o 
Out[3]: 0 

In [4]: subprocess.call(['ls', '-%sl' %'a'], shell=True) 
a.out   ex1-7   hello.c   hello_2.o  lesson_1-5.c   temperature_ex1-4.c 
ex1-6   ex1-7.c   hello.o   hello_3.o  temperature.o   temperature_ex1-5.c 
ex1-6.c   hello   hello_1.o  lesson_1-5  temperature_ex1-3.c  temperature_ex1-5.o 
Out[4]: 0 

In [6]: subprocess.call(['ls', '-al'])  
total 320 
drwxr-xr-x 20 Kohaugustine staff 680 Oct 15 16:55 . 
drwxr-xr-x 5 Kohaugustine staff 170 Sep 12 17:16 .. 
-rwxr-xr-x 1 Kohaugustine staff 8544 Oct 15 16:55 a.out 
-rwxr-xr-x 1 Kohaugustine staff 8544 Oct 3 10:28 ex1-6 
[email protected] 1 Kohaugustine staff 204 Oct 3 10:28 ex1-6.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Oct 3 10:15 ex1-7 
[email protected] 1 Kohaugustine staff 71 Oct 3 10:15 ex1-7.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:22 hello 
[email protected] 1 Kohaugustine staff 58 Sep 12 16:27 hello.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:24 hello.o 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:24 hello_1.o 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:27 hello_2.o 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 12 16:27 hello_3.o 
-rwxr-xr-x 1 Kohaugustine staff 8544 Oct 15 16:55 lesson_1-5 
[email protected] 1 Kohaugustine staff 185 Sep 28 10:35 lesson_1-5.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 21 10:06 temperature.o 
[email protected] 1 Kohaugustine staff 406 Sep 21 09:54 temperature_ex1-3.c 
[email protected] 1 Kohaugustine staff 582 Sep 21 10:06 temperature_ex1-4.c 
[email protected] 1 Kohaugustine staff 178 Sep 23 17:21 temperature_ex1-5.c 
-rwxr-xr-x 1 Kohaugustine staff 8496 Sep 23 17:21 temperature_ex1-5.o 
Out[6]: 0 

In [7]: subprocess.call(['ls', '-al'], shell = True) 
a.out   ex1-7   hello.c   hello_2.o  lesson_1-5.c   temperature_ex1-4.c 
ex1-6   ex1-7.c   hello.o   hello_3.o  temperature.o   temperature_ex1-5.c 
ex1-6.c   hello   hello_1.o  lesson_1-5  temperature_ex1-3.c  temperature_ex1-5.o 
Out[7]: 0 

好像每當殼=真,輸出似乎是相同的:

In [9]: subprocess.call(['ls']) 
a.out   ex1-7   hello.c   hello_2.o  lesson_1-5.c   temperature_ex1-4.c 
ex1-6   ex1-7.c   hello.o   hello_3.o  temperature.o   temperature_ex1-5.c 
ex1-6.c   hello   hello_1.o  lesson_1-5  temperature_ex1-3.c  temperature_ex1-5.o 
Out[9]: 0 

我感到困惑;當我設置shell = True時,'-a'選項發生了什麼?殼沒有讀過它嗎?我讀過Docs,它說當shell = True時,這意味着我的指定命令將通過shell執行,所以它應該表示ls -a被提供給shell並由shell執行。那麼爲什麼[4]和[7]中的行爲? 此外pydocs不直接解釋它(雖然它確實說當我們設置shell = False時,子進程不會做什麼);當我們讓shell = False時,這意味着什麼?在操作系統中產生了一個新的進程而沒有shell實際控制它?另外,如果我在[3]和[4]中使用的格式字符串看起來很尷尬,它的原因是在我的實際腳本中我將使用subprocess.call,所以我將不得不以依靠這些格式字符串來替換適當的命令選項。我無法硬編碼一些命令行選項。在參數中使用純字符串也是不可能的,因爲在我的腳本中會有一個方法需要對命令執行列表操作。我不知道是否有更好的方法可以解決這個問題,所以如果任何人都可以提出不同的建議,那麼如果真的有所幫助的話。

非常感謝!

+0

您可以選擇一個文件較少的目錄,以使您的示例更加簡潔易讀:) – GreenAsJade 2014-10-17 04:03:42

+0

相關Python問題:[不要在子進程中使用list參數和shell = True](http ://bugs.python.org/issue21347) – jfs 2014-10-17 21:55:12

回答

6

shell爲真時,第一個參數被附加到["/bin/sh", "-c"]。如果這樣的說法是一個列表,結果列表是

["/bin/sh", "-c", "ls", "-al"] 

也就是說,只有ls,不ls -al作爲參數傳遞給-c選項。 -al被用作shell本身的第一個參數,而不是ls

當使用shell=True時,通常只需傳遞一個字符串,並讓shell根據shell的正常分詞規則對其進行分割。

# Produces ["/bin/sh", "-c", "ls -al"] 
subprocess.call("ls -al", shell=True) 

就你而言,它看起來並不像你需要使用shell=True

+1

非常感謝!這使得現在更有意義!這應該包含在文檔中。 – AKKO 2014-10-23 03:17:47

1

當您將shell=True與一個列表一起使用時,額外參數將傳遞給外殼本身,而不是在外殼中運行的命令。然後,他們可以從shell腳本(如argv[0]通過)爲$0$1中提到,等

最簡單的答案是「不這樣做」:如果你想傳遞一個清單,不使用shell=True;如果要傳遞字符串,請始終使用shell=True


這就是說,它可能以這樣的方式來讀取這些參數來形成你的命令。下面是一個違反我的上述規則的例子 - 你不能實現的命令[*]沒有shell=True(和/bin/sh bash提供),因爲它依賴於bash的內置版本printf(它支持%q作爲擴展):

subprocess.call([ 
    "printf '%q\\n' \"$0\" \"[email protected]\"", 
    'these strings are\r\n', 
    '"shell escaped" in the output from this command', 
    "so that they can *safely* be run through eval" 
], shell=True) 

[*] - 不是真的;可以使用/bin/bash作爲argv[0]shell=False以更可靠地實現這一點,因爲它將不再取決於您的/bin/shbash

+0

非常感謝您的幫助!我想我會保持簡單而不使用shell = True,但是看到有可能仍然使用它並讓shell解釋列表中的所有參數,這很有趣。唯一的問題是,它打印出所有'\'反斜槓字符,這不會是好事,因爲我需要命令在由空格分隔的連續行中。 – AKKO 2014-10-23 03:21:13