2010-06-06 3 views
4

Je souhaite exécuter un programme externe dans chaque thread d'un programme python multithread. Disons que le temps de fonctionnement maximum est défini sur 1 seconde. Si le processus démarré se termine dans un délai d'une seconde, le programme principal capture sa sortie pour un traitement ultérieur. S'il ne se termine pas en 1 seconde, le programme principal le termine et lance un nouveau processus.Exécution d'un programme externe avec la durée d'exécution maximale spécifiée

Comment implémenter cela?

+0

connexes: [subprocess avec délai d'attente] (http://stackoverflow.com/q/1191374/4279) – jfs

+0

liés: [Arrêter la lecture de sortie de processus en Python sans accrocher?] (http: //stackoverflow.com/a/4418891/4279) – jfs

Répondre

6

Vous pouvez interroger périodiquement:

import subprocess, time 

s = subprocess.Popen(['foo', 'args']) 
timeout = 1 
poll_period = 0.1 
s.poll() 
while s.returncode is None and timeout > 0: 
    time.sleep(poll_period) 
    timeout -= poll_period 
    s.poll() 
if timeout <= 0: 
    s.kill() # timed out 
else: 
    pass # completed 

Vous pouvez simplement mettre ci-dessus dans une fonction et commencer comme un fil.

+0

il ne capture pas la sortie de l'enfant. – jfs

1

Un vilain hack sur Linux consiste à utiliser le programme timeout pour exécuter la commande. Cependant, vous pouvez opter pour une solution Python plus agréable.

2

C'est la fonction d'aide que j'utilise:

def run_with_timeout(command, timeout): 
    import time 
    import subprocess 

    p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

    while timeout > 0: 
     if p.poll() is not None: 
      return p.communicate() 
     time.sleep(0.1) 
     timeout -= 0.1 
    else: 
     try: 
      p.kill() 
     except OSError as e: 
      if e.errno != 3: 
       raise 
    return (None, None) 
+0

Comme ça :-) Fonctionne bien pour nous - merci! –

+0

1. Il ne renvoie aucune sortie si 'commande' génère une grosse sortie (assez pour remplir son tampon de sortie stdout/stderr). Vous devriez lire la sortie en attendant le timeout. 2. (détail mineur) Si 'timeout' est grand alors la boucle dérive parce que' time.sleep (0.1) 'peut dormir moins /' 0.1' secondes. Vous pouvez utiliser 'while while endtime> timer():' à la place. – jfs

1

est une solution ici en utilisant le module pexpect (je avais besoin pour capturer la sortie du programme avant qu'il a couru dans le délai d'attente, je ne l'ai pas réussi à faire cela avec subprocess.Popen):

import pexpect 

timeout = ... # timeout in seconds 

proc = pexpect.spawn('foo', ['args'], timeout = timeout) 

result = proc.expect([ pexpect.EOF, pexpect.TIMEOUT]) 

if result == 0: 
    # program terminated by itself 
    ... 
else: 
    # result is 1 here, we ran into the timeout 
    ... 

print "program's output:", print proc.before 
Questions connexes