Python Subprocess Grep

Estoy tratando de usar el comando grep en un script de python usando el módulo de subproceso.

Esto es lo que tengo:

userid = 'foo12' p = subprocess.Popen(['grep', "%s *.log"%userid], stdout=subprocess.PIPE) 

Y no devuelve nada. No estoy completamente seguro de lo que estoy haciendo mal, así que alguien puede explicarlo. El método actual que estoy usando y que funciona es agregar el shell = true que hace que produzca el resultado correcto, pero como las páginas de ayuda han señalado, no es seguro. Necesito ayuda para tratar de hacer que esto funcione para que mi script no sea inseguro.

Creo que te estás enfrentando a dos problemas:

  1. Esta llamada:

     p = subprocess.Popen(['grep', "%s *.log"%userid]... 

    no funcionará como se espera sin shell=True porque la lista de argumentos se pasa directamente a os.execvp , lo que requiere que cada elemento sea una única cadena que represente un argumento. Has aplastado dos argumentos separados juntos en una sola cadena (en otras palabras, grep está interpretando ” foo12 *.log ” como el patrón a buscar, y no la lista de patrones + archivos).

    Puedes arreglar esto diciendo:

     p = subprocess.Popen(['grep', userid, '*.log']...) 
  2. El segundo problema es que, nuevamente sin shell=True , execvp no sabe lo que quiere decir con *.log y lo pasa directamente a grep, sin pasar por el mecanismo de expansión de comodines de la shell. Si no quieres usar shell=True , puedes hacer algo como:

     import glob args = ['grep', userid] args.extend(glob.glob('*.log') p = subprocess.Popen(args, ...) 

Aquí hay dos piezas probadas de código para modelar desde:

 >>> print subprocess.check_output(['grep', 'python', 'api_talk.txt']) Discuss python API patterns Limitations of python Introspection in python >>> print subprocess.check_output('grep python *.txt', shell=True) 

Use este último si desea que el shell realice una expansión de comodín por usted. Cuando el shell es True , asegúrese de colocar todo el comando en una sola cadena en lugar de en una lista de campos separados.

Supongo que desea grep para ‘foo12’ en todos los archivos que terminan con ‘.log’, para que esto funcione solo con el subprocess deberá cambiar su código a lo siguiente:

 userid = 'foo12' p = subprocess.Popen('grep %s *.log' % userid, stdout=subprocess.PIPE, shell=True) 

shell=True es necesario para la expansión de comodines, y cuando se establece esa opción, debe proporcionar un comando de cadena en lugar de una lista.

Además, asegúrese de que cuando proporcione una lista de argumentos de que cada argumento sea una entrada separada en la lista, su código inicial hubiera sido equivalente a lo siguiente:

 grep 'foo12 *.log'