Op 2005-12-16, Sergey schreef <s3**@mail.ru >:
How to send alarm to a thread?
I can set alarm in main thread, but how then send exception to another thread to wake it if it executes too long?
The short answer is you can't and you should preferably look for an
other solution. If for example your other thread is simple loop
like:
while condition:
...
You could change this to:
while not timeout and condition:
timeout is then a variable that could be set by a differnt thread.
If your code doesn't lend itself for this kind of solution you could
consider the following module I once wrote. However some caveats:
1) You need ctypes.
2) It can only interrupt a thread while it is excuting python
code. No interruptions while in C-extention code.
3) It is not extensivly tested. It was just a proof of concept
thing.
----
import os
import ctypes
from time import sleep
from random import randint
class TimeOut(Excepti on):
pass
class Alarm(Exception ):
pass
import threading
class Xthread(threadi ng.Thread):
def start(self):
self.__original _run = self.run
self.run = self.__run
threading.Threa d.start(self)
def __run(self):
self._thrd_id = threading._get_ ident()
try:
self.__original _run()
finally:
self.run = self.__original _run
def raize(self, excpt):
Nr = ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf._thrd_id, ctypes.py_objec t(excpt))
#print self.id , "Exception Thrown" , Nr
while Nr > 1:
#print self.id , "Exception Canceled" , Nr
ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf._thrd_id, None)
sleep(0.1)
Nr = ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf._thrd_id, ctypes.py_objec t(excpt))
#if Nr == 0:
# print self.id , "Exception Canceled" , Nr
# ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf._thrd_id, None)
def alarm(self, tm):
alrm = threading.Timer (tm, self.raize, (TimeOut,))
alrm.start()
return alrm
if __name__ == "__main__":
class Continue(Xthrea d):
def run(self):
self.id = os.getpid()
print self.id, self._thrd_id, "Begin"
i = 0
try:
for _ in xrange(randint( 0,20)):
for e in xrange(4 * 100000):
i = i + e
print self.id, "Finished"
except Alarm:
print self.id, "Interupted "
lst = [Continue() for _ in xrange(10)]
for T in lst:
T.start()
try:
sleep(10)
finally:
for T in lst:
T.raize(Alarm)