2012-05-21 18 views
16

Quiero llamar a scripts desde un directorio (son scripts de shell ejecutables) a través de python.Tubería popen stderr y stdout

hasta ahora tan bueno:

for script in sorted(os.listdir(initdir), reverse=reverse): 
     if script.endswith('.*~') or script == 'README': 
      continue 
     if os.access(script, os.X_OK): 
      try: 
       execute = os.path.abspath(script) 
       sp.Popen((execute, 'stop' if reverse else 'start'), 
         stdin=None, stderr=sp.PIPE, 
         stdout=sp.stderr, shell=True).communicate() 
      except: 
       raise 

Ahora lo que quiero es: Digamos que tengo un script bash con un functiont inicio. de la que yo llamo

echo "Algo"

Ahora quiero ver ese eco en sys.stdout y el código de salida. Creo que haces esto con .communicate() pero el mío no funciona como pensé.

¿Qué estoy haciendo mal?

cualquier ayuda se agradece mucho

Respuesta

49

Confer http://docs.python.org/library/subprocess.html.

communicate() devuelve una tupla (stdoutdata, stderrdata).

Después de que el subproceso ha terminado, se puede obtener el código de retorno de la instancia Popen:

Popen.returncode: El código de retorno del niño, establecido por sondeo() y wait() (e indirectamente por comunicar()).

Del mismo modo, se puede lograr sus objetivos así:

sp = subprocess.Popen([executable, arg1, arg2], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
out, err = sp.communicate() 
if out: 
    print "standard output of subprocess:" 
    print out 
if err: 
    print "standard error of subprocess:" 
    print err 
print "returncode of subprocess:" 
print sp.returncode 

Por cierto, que cambiaría la prueba

if script.endswith('.*~') or script == 'README': 
     continue 

en una positiva:

if not filename.endswith(".sh"): 
    continue 

Es mejor ser explícito sobre lo que le gustaría exponer ecute que ser explícito sobre lo que hace no desea ejecutar.

Además, debe nombrar sus variables de forma más general, por lo que script debe ser filename en primer lugar. Como listdir también enumera directorios, puede verificarlos explícitamente. Su bloque actual try/except no es apropiado siempre que no maneje una excepción específica. En lugar de abspath, solo debe concatenar initdir y filename, que es un concepto que se aplica a menudo en el contexto de os.listdir(). Por razones de seguridad, use shell=True en el constructor del objeto Popen solo si está absolutamente seguro de que lo necesita. Permítanme sugerir lo siguiente:

for filename in sorted(os.listdir(initdir), reverse=reverse): 
    if os.path.isdir(filename) or not filename.endswith(".sh"): 
     continue 
    if os.access(script, os.X_OK): 
     exepath = os.path.join(initdir, filename) 
     sp = subprocess.Popen(
      (exepath, 'stop' if reverse else 'start'), 
      stderr=subprocess.PIPE, 
      stdout=subprocess.PIPE) 
     out, err = sp.communicate() 
     print out, err, sp.returncode 
+0

Muchas gracias –

+0

Sí, tengo excepciones específicas sólo que no las escriba de porque tu no son pertinentes a la cuestión. Pero tienes razón sobre los nombres de las variables, siempre lucho con nombres propios así que gracias de nuevo –

Cuestiones relacionadas