El módulo de subproceso no ejecuta el comando

Estoy intentando ejecutar cpplint.py de Google en un grupo de mis archivos y recostackr los resultados en un archivo de registro. Sin embargo, no he logrado superar el módulo de subproceso. Mi código actual está aquí:

import os, subprocess rootdir = "C:/users/me/Documents/dev/" srcdir = "project/src/" with open(rootdir+srcdir+"log.txt", mode='w', encoding='utf-8') as logfile: for subdir, dirs, files in os.walk(rootdir+srcdir): for file in files: if file.endswith(".h") or file.endswith(".cpp"): filewithpath=os.path.join(subdir, file) cmd=['c:/Python27/python.exe','C:/users/me/Documents/dev/cpplint.py','--filter=-whitespace,-legal,-build/include,-build/header_guard/', filewithpath] output = subprocess.check_output(cmd) logfile.write(output.decode('ascii')) 

Intentar ejecutar el código anterior genera un error:

  File "C:\Python32\lib\site.py", line 159 file=sys.stderr) ^ SyntaxError: invalid syntax Traceback (most recent call last): File "C:\Users\me\Documents\dev\project\src\verifier.py", line 19, in  output = subprocess.check_output(cmd) File "C:\Python32\lib\subprocess.py", line 511, in check_output raise CalledProcessError(retcode, cmd, output=output) subprocess.CalledProcessError: Command '['c:/Python27/python.exe', 'C:/users/me/Documents/dev/cpplint.py', '--filter=-whitespace,-legal,-build/include,-build/header_guard/', 'C:/users/me/Documents/dev/project/src/aboutdialog.cpp']' returned non-zero exit status 1 

Si sustituyo el cmd con algo más simple como:

 cmd=['C:/WinAVR-20100110/bin/avr-gcc.exe','--version'] 

Entonces el guión funciona como se espera.

También he intentado usar una única cadena de comando en lugar de una lista de cadenas como cmd, pero el resultado es el mismo. Al depurar el código, copié el comando del depurador de la lista de cadenas convertidas en la línea de comandos y lo ejecuté en la línea de comandos de Windows, y el comando se ejecutó como se esperaba.

El intérprete de Python que ejecuta mi script es Python 3.2. Cualquier consejo es muy apreciado.

Parece que cpplint.py simplemente está saliendo con un código de retorno distinto de cero, lo que podría hacer, por ejemplo, si encuentra errores o “pelusa” en los archivos de origen que está verificando.

Consulte la documentación para subprocess.check_output . Tenga en cuenta que si el comando ejecutado devuelve un código de salida distinto de cero, se subprocess.CalledProcessError un subprocess.CalledProcessError .

Podría CalledProcessError observando CalledProcessError , por ejemplo,

 try: output = subprocess.check_output(cmd) except subprocess.CalledProcessError as e: # ack! cpplint.py failed... report an error to the user? 

EDITAR :

El SyntaxError parece ser la clave aquí, y probablemente se deba a que C:\Python32\lib está en su PYTHONPATH (ya sea explícitamente o, esto podría suceder si es su directorio de trabajo actual).

El intérprete de Python (desde aproximadamente 1.5.2-ish) ejecuta automáticamente el import site cuando se inicia. Entonces, cuando este es el caso, y su script va a ejecutarse:

 c:/Python27/python.exe C:/users/me/Documents/dev/cpplint.py ... 

luego, el intérprete de Python 2.7 encontrará C:\Python32\lib\site.py primero, e intentará cargar eso, en lugar de uno (probablemente) en C:\Python27\lib\site.py El problema es que el site.py Python 3 contiene una syntax incompatible con Python 2, por lo que el proceso iniciado por subprocess.check_output está fallando con un SyntaxError antes de que incluso tenga la oportunidad de ejecutar cpplint , que propaga el CalledProcessError .

¿Solución? Asegúrate de que Python2 reciba una buena reputación de Python2 “PYTHONPATH”, y lo mismo para Python3! En otras palabras, asegúrese de que C:\Python32\lib no esté en la ruta de búsqueda de PYTHONPATH al ejecutar el intérprete de Python2.

Una forma de hacer esto en su caso es establecer un entorno explícito al iniciar el proceso, por ejemplo:

 python2_env = {"PYTHONPATH": "path/to/python2/stuff:..."} output = subprocess.check_output(cmd, env=python2_env) 

Te pido que ejecutes esto primero

 pipe = subprocess.Popen([cmd, options],stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = pipe.communicate() 

Usted sabrá exactamente cuál es el error detrás de él, ya que CalledProcessError se genera solo si el código de salida no es cero.

Lo hice reemplazando def main () con lo siguiente (también edito la función de error para obtener un archivo csv adecuado):

 errorlog = sys.stderr sys.stderr = open("errorlog.csv","w") sys.stderr.write("File;Line;Message;Category;Confidence\n") for filename in filenames: ProcessFile(filename, _cpplint_state.verbose_level) _cpplint_state.PrintErrorCounts() sys.exit(_cpplint_state.error_count > 0) sys.stdout = errorlog sys.stderr.close()