2009-10-12 5 views
8

Possible en double:
subprocess with timeoutpython: lancer un processus avec temporisation et stdout de capture, stderr et état de sortie

Quelle est la meilleure façon de faire ce qui suit en Python:

  • Exécution d'un processus externe
  • Capture stdout dans une chaîne, stderr et état de sortie
  • Définissez un délai d'expiration.

Je voudrais quelque chose comme ceci:

import proc 

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

Juste pour que nous savons où vous êtes à partir, avez-vous pensé le module 'subprocess'? http://docs.python.org/library/subprocess.html –

+0

non - on dirait que c'est un grand pas en avant – flybywire

+1

sous-processus 'Popen.communicate avec timeout, question similaire: http://stackoverflow.com/questions/1191374/ subprocess-with-timeout – Mark

Répondre

12

Je déteste faire le travail par moi-même. Copiez simplement ceci dans votre module 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

Cette version peut expirer en raison d'un débordement de tampon de tuyau (lorsque stdout ou stderr ~ 64K). – jfs

+1

Si la commande arrive à expiration, vous n'obtiendrez aucune sortie générée jusqu'au délai d'expiration. –

+0

print run (["ping www.redicecn.com"], timeout = 10), le script a rejeté l'exception Timeout, mais le processus ping était toujours en cours d'exécution. – redice

11

Note sur linux avec coreutils> = 7.0 vous pouvez préfixer délai d'attente à la commande comme:

timeout 1 sleep 1000 
Questions connexes