Seite 1 von 1

subprocess timeout

Verfasst: Freitag 25. März 2011, 22:41
von glaslos
Hallo, ich würde gerne folgenden Code durch subprocess ersetzen:

Code: Alles auswählen

f = os.fork()

    if f < 0:
        print 'error launching!'
        usage()
    elif f > 0:
        # parent
        print 'launching child script, PID is %s' % f
        print 'sleeping for %d seconds ...' % secs
        time.sleep(secs)
        print 'Killing processes ...'
        os.system("kill `ps ax | grep scrips.php | awk '{print $1}'`")
    elif f == 0:
        # child
        start = time.time()
        o, i, e = popen2.popen3('php scrips.php %s' % prog)
        err = e.read()
        out = o.read()
        i.close()
        e.close()
        o.close()
        end = time.time()
        print err
        analysis = distill(prog, start, end, err)
        sys.exit(0)
Ich gehe davon aus, dass das php script nicht fertig läuft und ich lese erfolgreich das resultat aus err aus.

Hier mein Ansatz:

Code: Alles auswählen

def sub_test(prog, secs):
    proc = subprocess.Popen(['php', 'script.php', prog],
                                shell = False,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                )
    print 'PARENT : Pausing before sending signal...'
    sys.stdout.flush()

    signal.signal(signal.SIGALRM, alarm_handler)
    signal.alarm(secs)
    stdout_value = ""
    stderr_value = ""
    try:
        stdout_value, stderr_value = proc.communicate()
        signal.alarm(0)
    except Alarm:
        print "Oops, taking too long!"
    finally:
        print "out", repr(stdout_value)
        print "err", repr(stderr_value)
    print 'PARENT : Signaling child'
    sys.stdout.flush()
    os.kill(proc.pid, signal.SIGKILL)
    sys.exit(0)
Läuft prima, aber wenn das Timeout erreicht wird, bricht das script ab aber stderr_out ist leer. Tipps?

Re: subprocess timeout

Verfasst: Freitag 25. März 2011, 23:20
von deets
Naja, das ist ja auch kein Wunder. Du unterbrichst ja den communicate()-Aufruf recht unsanft mit einem Alarm - wie soll der gute denn dann noch eine Zuweisung machen?

Das hier geht (threading statt Alarm, weil wegen simpler fuer mich - alarm sollte aber auch gehen):

Code: Alles auswählen

import subprocess
import threading
import time
from functools import partial

def killer(proc):
    time.sleep(3)
    print "killing in the name of..."
    proc.kill()

    
def sub_test():
    proc = subprocess.Popen(['python', '/tmp/stderrwriter.py'],
                                shell = False,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                )
    print 'PARENT : Pausing before sending signal...'

    #signal.signal(signal.SIGALRM, alarm_handler)
    #signal.alarm(secs)
    threading.Thread(target=partial(killer, proc)).start()
    stdout_value, stderr_value = proc.communicate()
    print "out", repr(stdout_value)
    print "err", repr(stderr_value)


sub_test()