2012-05-19 6 views
9

Parece que el uso de shell = True en el primer proceso de una cadena de alguna manera cae la salida estándar de tareas downstream:¿Por qué Shell = True come mi subproceso.Pobre stdout?

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

Hacer la cáscara del primer uso = True proceso mata a la salida de alguna manera ...

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

shell = Verdadero en el segundo proceso no parece importar. ¿Es este comportamiento esperado?

Respuesta

15

Al pasar shell=True, Popen espera un argumento de cadena única, no una lista. Así que cuando usted hace esto:

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

Lo que ocurre es lo siguiente:

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

Es decir, que llama sh -c "echo" y hello se ignora efectivamente (técnicamente se convierte en un argumento posicional a la cáscara). Entonces el intérprete de comandos ejecuta echo, que imprime \n, por lo que puede verlo en su salida.

Si utiliza shell=True, lo que necesita hacer esto:

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

Gracias! Para la posteridad, aquí está el [docs] (http://docs.python.org/library/subprocess.html): En Unix, con shell = True: si args es una secuencia, el primer elemento especifica la cadena de comandos, y cualquier elemento adicional se tratará como argumentos adicionales para el propio shell. Es decir, Popen hace el equivalente de: 'Popen (['/ bin/sh', '-c', args [0], args [1], ...])' –

+0

muy poco documentado, En mi humilde opinión – Davide

Cuestiones relacionadas