2012-05-19 9 views
9

チェーン何とか下流の作業から標準出力をドロップする最初の過程で真のシェルを=使用しているようだ:なぜshell = Trueは私のサブプロセスを食べますか?

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

を= Trueのは...何とか

p1 = Popen(['echo','hello'], stdout=PIPE, shell=True) 
p2 = Popen('cat', stdin=p1.stdout, stdout=PIPE) 
p2.communicate() 
# outputs incorrectly ('\n', None) 
を出力を殺す最初のプロセスの使用シェルを作ります

shell = 2番目のプロセスでTrueとは関係ありません。これは予想される動作ですか?

答えて

15

shell=Trueを渡すと、Popenはリストではなく1つの文字列引数を要求します。だから、あなたがこれを行うとき:

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

は何が起こるかというと、このです:ある

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

を、それがsh -c "echo"を呼び出し、helloが効果的に無視されます(技術的には、シェルに位置引数になります)。したがって、シェルは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がシーケンスである場合、最初の項目はコマンド文字列を指定し、追加の項目はシェル自体に対する追加の引数として扱われます。つまり、Popenは以下のようなことをします: 'Popen(['/ bin/sh'、 '-c'、args [0]、args [1]、...])' –

+0

は、私見では – Davide

関連する問題