2012-04-03 13 views
37
import os 

import subprocess 

proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

out,err = proc.communicate() 

print out 

Este script debe imprimir todos los archivos con el sufijo .bc pero devuelve una lista vacía. Si hago ls * .bc manualmente en la línea de comandos, funciona. Hacer ['ls', 'test.bc'] dentro del script también funciona, pero por alguna razón el símbolo de estrella no funciona ... ¿Alguna idea?Uso del comodín del subproceso de Python

+0

relacionados: [Comodín no funciona en llamadas de subproceso usando shlex] (http: // stackoverf low.com/q/7156892/4279) – jfs

Respuesta

41

Debe suministrar shell=True para ejecutar el comando a través de un intérprete de shell. Sin embargo, si lo hace, ya no puede proporcionar una lista como primer argumento, porque los argumentos serán citados a continuación. En su lugar, especifique la línea de comandos en bruto a medida que desea que se pasa a la consola:

proc = subprocess.Popen('ls *.bc', shell=True, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE) 
+0

Gracias, funcionó bien. Algunos de los ejemplos que encontré en Internet tenían una lista como su primer argumento por alguna razón – Cemre

+9

@Cemre: Suele ser aconsejable porque * no * quiere que el intérprete interprete los argumentos. Imagine que pasa la entrada del usuario a un comando como en '' ls '+ user_supplied_path'. El usuario podría simplemente ingresar la ruta '; shutdown -s' y el sistema se detendría! Si usa '['ls', user_supplied_path]', evitará este tipo de inyección. –

37

Ampliar el pegote * es parte de la concha, pero por defecto subprocess hace no enviar sus órdenes a través de una concha, por lo el comando (primer argumento, ls) se ejecuta, luego se usa un literal * como argumento.

Esto es una buena cosa, vea the warning block in the "Frequently Used Arguments" section, de los documentos del subproceso. Se discuten principalmente las implicaciones de seguridad, pero también puede ayudar a evitar errores de programación tontos (ya que no hay que preocuparse por los personajes mágicos)

Mi principal queja con shell=True es que generalmente implica que hay una mejor manera de solucionar el problema - con su ejemplo, debe utilizar the glob module:

import glob 
files = glob.glob("*.bc") 
print files # ['file1.bc', 'file2.bc'] 

Esto será más rápido (sin proceso de inicio de gastos generales), la plataforma más fiable y transversal (no dependiente de la plataforma que tiene un comando ls)

+0

'subproceso no envía sus comandos a través de un shell' ¿Por qué? ¿Puede proporcionarnos alguna referencia? Gracias – Stallman

+0

Además, proporciona un objeto python para trabajar y manipular. Esta debería ser la respuesta seleccionada. Mucho más amigable con 'python'. – Cyan

Cuestiones relacionadas