Seite 1 von 1

funktionen mit timeout

Verfasst: Freitag 3. Juli 2009, 11:25
von INFACT
Liebes Forum,
Ich habe ein paar funktionen, die unter umständen sehr lange dauern. Jetzt möchte ich eine Funktion bauen, die diese funktion ausführt, aber wenn sie mehr als zb. 60 sec. braucht, diese abbricht und einen timeouterror wirft. Das ist mein Code, der leider i-wie nicht klappt:

Code: Alles auswählen

import time, thread

class timeouterror(Exception):
    pass

def timeout(times, func, *args, **kwargs):
    "time = time in seconds to throw error"
    global seconds, running
    global func2, update
    running = False
    seconds = 0
    was_running = False
    ret = "xxxxxxxxx"
    def func2():
        global seconds, running
        running = True
        if args:
            a = func (args, kwargs)
        else:
            a = func ()

        running = False
        ret = a
        was_running = True

    def update():
        global seconds, running
        while 1:
            print "not running"
            if running:
                print seconds, times
                if seconds >= times:
                    ret = False
                seconds += 1
                time.sleep(1)
                print seconds
            if was_running == True:
                break

    thread.start_new_thread(update,tuple())
    thread.start_new_thread(func2,tuple())
    while ret == "xxxxxxxxx":
        pass
    print ret

def foo():
    time.sleep(10)

if __name__ == '__main__':
    timeout(5, foo)
    

        
Bin für alle vorschläge offen.
MfG Robin

Verfasst: Freitag 3. Juli 2009, 11:35
von ms4py
Warum nicht so:
Edit: erweitert mit Event, damit der Thread beendet werden kann.

Code: Alles auswählen

event = threading.Event()
event.set()
def func():
  while event.is_set():
    pass
thread = threading.Thread(target=func)
thread.start()
thread.join(60) #seconds
if thread.is_alive():
  event.clear()
  raise Exception("thread not terminated yet")


Verfasst: Freitag 3. Juli 2009, 11:48
von Zap
Erstmal solltest du dir ganz schnell den schlechten Stil mit globals abgewöhnen.
Auch die Closure Functions machen meiner Meinung nach wenig Sinn.
Benutze das Modul threading anstelle von thread
Sorry, aber dein Code ist ein super Beispiel für ein schlechtes Beispiel ;)

Ohne deinen Code jetzt im Detail nachvollzogen zu haben,
hier mal ein schnelles Beispiel:

Code: Alles auswählen

import time
from threading import Thread

class TimeoutExample(Thread):
    
    def __init__(self, timeout, *args, **kwargs):
        self.timeout = timeout
        self._start = None
        Thread.__init__(self, *args, **kwargs)
        
    def run(self):
        self._start = time.time()
        while (time.time() - self._start) < self.timeout:
            print "doing something"
            time.sleep(1)
        print "done"
        
th = TimeoutExample(4)
th.start()
th.join()

Verfasst: Freitag 3. Juli 2009, 12:09
von INFACT
@ice2k3:

Code: Alles auswählen

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
    self.run()
  File "C:\Python25\lib\threading.py", line 446, in run
    self.__target(*self.__args, **self.__kwargs)
  File "H:/Desktop/Hacking/vulnscanner/c.ppy", line 5, in func
    while event.is_set():
AttributeError: '_Event' object has no attribute 'is_set'


Traceback (most recent call last):
  File "H:/Desktop/Hacking/vulnscanner/c.ppy", line 10, in <module>
    if thread.is_alive():
AttributeError: 'Thread' object has no attribute 'is_alive'
ich benutze python 2.5

@Zap: Mit einer while schleife hätte ich das auch hinbekommen... doch leider ist das eine funktion die nur eine Sache macht, die sich nicht wiederholt. Wie wenn ich einen 200 Gb dateinbank eintrag recherchiere oder so.

Edit: Mit den globals mach ich auch sonst nicht... Python spinnt bloß im moment ein bisschen, ich muss sys.path immer wieder um \site-packages ergänzen und viele Sachen funkitonieren nicht... Ich werds vielleicht mal reinstallieren

Verfasst: Freitag 3. Juli 2009, 12:32
von Zap
INFACT hat geschrieben: @Zap: Mit einer while schleife hätte ich das auch hinbekommen... doch leider ist das eine funktion die nur eine Sache macht, die sich nicht wiederholt. Wie wenn ich einen 200 Gb dateinbank eintrag recherchiere oder so.
Wenn du Einfluss auf diese Funktion hast solltest du dessen Arbeit aber aber vielleicht irgendwie über eine Schleife durchführen und entsprechend auf Events von außen reagieren.
Wenn du irgendwelche IO Aktionen tätigst solltest du vielleicht überlegen diese in einzelne Schritte aufzuteilen.
Man kann einige Operationen nicht ohne weiteres von außen abbrechen und einen laufenden Thread wärend solcher Operation knallhart zu beenden ist ebenfalls sehr unsauber.

Verfasst: Freitag 3. Juli 2009, 14:17
von fred.reichbier
Hi,

ich hab da letztens das hier gefunden, vielleicht hilft das ja.

Gruß,

Fred

Verfasst: Samstag 4. Juli 2009, 17:11
von INFACT
Danke, das hilft!

Verfasst: Montag 6. Juli 2009, 11:32
von ms4py
In Python 2.5 heißen die Methoden vermutlich isSet und isAlive.
(Bei sowas kann man auch mal in der Doku schauen...)