2012-05-19 55 views
9

看來,使用shell =鏈中的第一個過程真不知何故下降,從下游任務的標準輸出:爲什麼shell = True吃我的subprocess.Popen標準輸出?

p1 = Popen(['echo','hello'], stdout=PIPE) 
p2 = Popen('cat', stdin=p1.stdout, stdout=PIPE) 
p2.communicate() 
# outputs correctly ('hello\n', None) 

使第一過程中使用殼=真殺死輸出莫名其妙...

p1 = Popen(['echo','hello'], stdout=PIPE, shell=True) 
p2 = Popen('cat', stdin=p1.stdout, stdout=PIPE) 
p2.communicate() 
# outputs incorrectly ('\n', None) 

shell = True對第二個進程似乎並不重要。這是預期的行爲?

回答

15

當您通過shell=True時,Popen需要一個字符串參數,而不是一個列表。所以,當你這樣做:

p1 = Popen(['echo','hello'], stdout=PIPE, shell=True) 

什麼情況是這樣的:

execve("/bin/sh", ["/bin/sh", "-c", "echo", "hello"], ...) 

也就是說,它會調用sh -c "echo"hello有效地忽略(在技術上它變成一個位置參數的shell)。所以外殼運行echo,它打印\n,這就是爲什麼你在你的輸出中看到。

如果使用shell=True,你需要這樣做:

p1 = Popen('echo hello', stdout=PIPE, shell=True) 
+3

謝謝!對於後人,這裏是[docs](http://docs.python.org/library/subprocess.html): 在Unix上,使用shell = True:如果args是一個序列,則第一項指定命令字符串,而其他任何項目都將被視爲shell本身的附加參數。也就是說,Popen相當於: 'Popen(['/ bin/sh','-c',args [0],args [1],...])' –

+0

記錄很差,恕我直言 – Davide

相關問題