2009-10-12 10 views
8

Eventuali duplicati:
subprocess with timeoutpython: eseguire un processo con timeout e la cattura stdout, stderr e stato di uscita

Qual è il modo più semplice per effettuare le seguenti operazioni in Python:

  • Esecuzione di un processo esterno
  • Cattura stdout in una stringa, stderr e stato di uscita
  • Imposta un timeout.

Vorrei qualcosa di simile:

import proc 

try: 
    status, stdout, stderr = proc.run(["ls", "-l"], timeout=10) 
except proc.Timeout: 
    print "failed" 
+2

solo per farci saper dove stai a partire da, avete considerato il modulo 'subprocess'? http://docs.python.org/library/subprocess.html –

+0

no - sembra che sia un grande salto in avanti – flybywire

+1

sottoprocesso 'Popen.communicate con timeout, domanda simile: http://stackoverflow.com/questions/1191374/ sottoprocesso con timeout – Mark

risposta

12

Odio fare il lavoro da solo. Copia questo nel tuo modulo proc.py.

import subprocess 
import time 
import sys 

class Timeout(Exception): 
    pass 

def run(command, timeout=10): 
    proc = subprocess.Popen(command, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    poll_seconds = .250 
    deadline = time.time()+timeout 
    while time.time() < deadline and proc.poll() == None: 
     time.sleep(poll_seconds) 

    if proc.poll() == None: 
     if float(sys.version[:3]) >= 2.6: 
      proc.terminate() 
     raise Timeout() 

    stdout, stderr = proc.communicate() 
    return stdout, stderr, proc.returncode 

if __name__=="__main__": 
    print run(["ls", "-l"]) 
    print run(["find", "/"], timeout=3) #should timeout 
+1

Questa versione potrebbe scadere a causa dell'overflow del buffer delle pipe (quando stdout o stderr ~ 64K). – jfs

+1

Se il comando scade, non si otterrà alcun output generato fino al timeout. –

+0

print run (["ping www.redicecn.com"], timeout = 10), lo script ha eliminato l'eccezione Timeout, ma il processo di ping era ancora in esecuzione. – redice

11

Nota su Linux con coreutils> = 7.0 è possibile anteporre timeout per il comando come:

timeout 1 sleep 1000 
Problemi correlati