2012-05-21 17 views
16

Voglio chiamare script da una directory (sono script di shell eseguibili) tramite python.Piping popen stderr e stdout

finora tutto bene:

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 

Ora quello che voglio è: Diciamo che ho uno script bash con un functiont inizio. da che io chiamo

echo "Something"

Ora voglio vedere che eco sulla sys.stdout e il codice di uscita. Credo che tu lo faccia con .communicate() ma il mio non funziona come pensavo.

Cosa sto sbagliando?

Qualsiasi aiuto è molto apprezzato

risposta

49

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

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

Dopo che il sottoprocesso è terminato, è possibile ottenere il codice di ritorno dall'istanza Popen:

Popen.returncode: Il codice di ritorno del bambino, fissato dal poll() ed attendere() (e indirettamente per comunicare()).

Allo stesso modo, è possibile raggiungere i vostri obiettivi così:

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 

A proposito, vorrei cambiare il test

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

in una positiva:

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

È meglio essere espliciti su ciò che vorresti esprimere ecuire di essere esplicito su ciò che fai non vuoi eseguire.

Inoltre, dovresti nominare le variabili in un modo più generale, quindi script dovrebbe essere filename in primo luogo. Come listdir elenca anche le directory, puoi verificarne esplicitamente quelle. Il tuo attuale blocco try/except non è corretto finché non gestisci un'eccezione specifica. Invece di abspath, è sufficiente concatenare initdir e filename, che è un concetto spesso applicato nel contesto di os.listdir(). Per motivi di sicurezza, utilizzare shell=True nel costruttore dell'oggetto Popen solo se si è assolutamente sicuri di averne bisogno. Mi permetto di suggerire il seguente:

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

ringrazio molto –

+0

Sì, ho eccezioni specifiche Io proprio non li ho tipo in causa tua non sono rilevanti per la domanda. Ma tu hai ragione sui nomi delle variabili, io lotto sempre con nomi propri quindi Grazie ancora –

Problemi correlati