2009-10-12 13 views
8

Powiel możliwe:
subprocess with timeoutpython: uruchomić proces z limitu czasu i przechwytywania stdout, stderr i stanu wyjścia

Jaki jest najprostszy sposób, aby wykonać następujące czynności w Pythonie:

  • Uruchom proces zewnętrzny
  • Przechwytuj standardowe wyjście w łańcuchu, stderr i kod zakończenia
  • Ustaw limit czasu.

chciałbym coś takiego:

import proc 

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

Tak więc wiemy, gdzie jesteś, począwszy od, czy za moduł 'subprocess'? http://docs.python.org/library/subprocess.html –

+0

nie - wygląda na to, że jest to duży krok naprzód – flybywire

+1

podproces "Popen.communicate z limitem czasu, podobne pytanie: http://stackoverflow.com/questions/1191374/ podproces-z-timeout – Mark

Odpowiedz

12

Nienawidzę wykonują pracę samodzielnie. Po prostu skopiuj to do swojego modułu 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

Ta wersja może przekroczyć limit czasu z powodu przepełnienia bufora potoku (gdy stdout lub stderr ~ 64K). – jfs

+1

Jeśli komenda zostanie przekroczona, nie zostanie wygenerowane żadne wyjście do czasu oczekiwania. –

+0

print run (["ping www.redicecn.com"], timeout = 10), skrypt wyłączył wyjątek Timeout, ale proces ping nadal działał. – redice

11

Uwaga na linux z coreutils> = 7,0 można poprzedzić czas oczekiwania na komendy:

timeout 1 sleep 1000 
Powiązane problemy