Python Popen Grep

Me gustaría que Popen ejecutara:

grep -i --line-buffered "grave" data/*.txt 

Cuando se ejecuta desde el shell, esto me da el resultado deseado. Si comienzo, en el mismo directorio donde grep , una respuesta de python y sigo las instrucciones de los documentos , obtengo cuál debería ser la lista de argumentos adecuada para alimentar a Popen con:

 ['grep', '-i', '--line-buffered', 'grave', 'data/*.txt'] 

El resultado de p = subprocess.Popen(args) es

 grep: data/*.txt: No such file or directory 

y si bash p = subprocess.Popen(args, shell=True) , obtengo:

 Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more information. 

¿Alguna ayuda sobre cómo realizar el proceso deseado? Estoy en MacOS Lion.

Si escribe * en bash, el shell lo expande a los archivos en el directorio dado antes de ejecutar el comando. Popen de Python no hace tal cosa, así que lo que está haciendo cuando llama a Popen de esa manera le está diciendo a grep que hay un archivo llamado *.txt en el directorio de data , en lugar de todos los archivos .txt en el directorio de data . Ese archivo no existe y obtienes el error esperado.

Para resolver esto, puede decirle a Python que ejecute el comando a través del shell pasando shell=True a Popen:

 subprocess.Popen('grep -i --line-buffered grave data/*.txt', shell=True) 

Que se traduce a:

 subprocess.Popen(['/bin/sh', '-c', 'grep -i --line-buffered "grave" data/*.txt']) 

Como se explica en la documentación de Popen .

/bin/sh -c "grep -i --line-buffered "grave" data/*.txt" usar una cadena en lugar de una lista aquí, porque quiere ejecutar /bin/sh -c "grep -i --line-buffered "grave" data/*.txt" (NB cita alrededor del comando, haciéndolo un solo argumento a sh ). Si usa una lista, este comando se ejecuta: /bin/sh -c grep -i --line-buffered "grave" data/*.txt , que le da la salida de simplemente ejecutar grep .

El problema es que el shell hace que el archivo se convierta por ti: data / *. Txt

Deberá hacerlo usted mismo, por ejemplo, utilizando el módulo glob .

 import glob cmd_line = ['grep', '-i', '--line-buffered', 'grave'] + glob.glob('data/*.txt')