Uso de comodines de subproceso de Python


import os

import subprocess

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

out,err = proc.communicate()

print out

Este script debería imprimir todos los archivos con .sufijo bc sin embargo devuelve una lista vacía. Si lo hago ls*.bc manualmente en la línea de comandos funciona. Haciendo ['ls','prueba.bc'] dentro del script también funciona, pero por alguna razón el símbolo de la estrella no funciona.. Alguna idea ?

Author: Cemre, 2012-04-03

2 answers

Necesita suministrar shell=True para ejecutar el comando a través de un intérprete de shell. Sin embargo, si hace eso, ya no puede proporcionar una lista como primer argumento, porque los argumentos se citarán entonces. En su lugar, especifique la línea de comandos sin procesar como desea que se pase al shell:

 proc = subprocess.Popen('ls *.bc', shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
 53
Author: Niklas B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-03 16:01:08

Expandiendo el * glob es parte del shell, pero por defecto subprocesshace no enviar sus comandos a través de un shell, por lo que el comando (primer argumento, ls) se ejecuta, luego se usa un * literal como argumento.

Esto es algo bueno, ver el bloque de advertencia en la sección "Argumentos de uso frecuente" , de los documentos del subproceso. Principalmente discute las implicaciones de seguridad, pero también puede ayudar a evitar errores de programación tontos (ya que no hay caracteres de shell mágicos para preocúpate por)

Mi principal queja con shell=True es que generalmente implica que hay una mejor manera de resolver el problema: con su ejemplo, debe usar el módulo glob :

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

Esto será más rápido (sin sobrecarga de inicio de proceso), más confiable y multiplataforma (no depende de que la plataforma tenga un comando ls)

 40
Author: dbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-28 01:05:24