Interrput a thread

Fuzzyman fuzzyman at gmail.com
Tue Jan 4 10:13:49 EST 2011


On Jan 4, 3:12 pm, Fuzzyman <fuzzy... at gmail.com> wrote:
> On Dec 29 2010, 11:31 pm, gervaz <ger... at gmail.com> wrote:
>
> > Hi all, I need to stop a threaded (using CTR+C or kill) application if
> > it runs too much or if I decide to resume the work later.
> > I come up with the following test implementation but I wanted some
> > suggestion from you on how I can implement what I need in a better or
> > more pythonic way. Here the code:
>
> This is a case that .NET (C#) handles better than Python or Java.
>

Heh, so one possible option is to use IronPython.... :-)

Michael Foord

> It is unsafe to terminate an os level thread at an arbitrary point
> because it may be executing code in a critical section. Both Java
> and .NET used to provide ways to terminate threads "safely" by raising
> an asynchronous exception in the thread. Releasing locks (etc) that
> the thread holds could then be done in a finally section protecting
> the code. Python doesn't allow you to abort threads.
>
> Unfortunately the thread abort exception could also be raised in the
> finally section - prematurely aborting the lock / resource cleanup.
>
> Java handled this by deprecating thread aborting. (Python has never
> had it I believe.)
>
> .NET handled it by changing the semantics of thread aborting - the
> thread abort exception will never be raised in a finally block. This
> makes thread aborting safe, although technically you can subvert it by
> putting all your code in a finally block (you can also catch and
> cancel the thread abort exception).
>
> The standard advice is to use a flag and do manual checking to abort
> threads. This only works for fine grained operations and *doesn't*
> work for very coarse grained operations or where there aren't
> convenient places to check the flag. It's another place where people
> sometimes have a genuine need/use case yet people will insist on
> telling them they don't *really* want it...
>
> Anyway, although there are ways based on ctypes to abort Python
> threads it's not really safe. If you google you should find them,
> hopefully with intelligible caveat emptor warnings...
>
> All the best,
>
> Michael Foord
>
>
>
> > import os
> > import signal
> > import time
> > from threading import Thread, current_thread
> > from queue import LifoQueue, Empty
>
> > COMMAND = {"STOP": 0, "NORMAL": 1}
> > THREAD_NUM = 5
>
> > lq = LifoQueue()
>
> > print("{0}\n".format(os.getpid()))
>
> > class InterceptInterrupt(Exception):
> >     pass
>
> > class Handler:
> >     def __init__(self, queue):
> >         self._queue = queue
> >     def __del__(self):
> >         print("Bye bye!")
> >     def getHandler(self, signum, frame):
> >         print("Interrupt raised!")
> >         for _ in range(THREAD_NUM):
> >             self._queue.put((COMMAND["STOP"], None))
> >         raise InterceptInterrupt
>
> > h = Handler(lq)
>
> > signal.signal(signal.SIGINT, h.getHandler)
>
> > for i in range(25):
> >     lq.put((COMMAND["NORMAL"], i))
>
> > def do_work(queue):
> >     while True:
> >         time.sleep(5)
> >         try:
> >             cmd, value = queue.get(block=False)
> >             if cmd == COMMAND["STOP"]:
> >                 print("{0}: STOP command
> > received!".format(current_thread().name))
> >                 break
> >             elif cmd == COMMAND["NORMAL"]:
> >                 print(value)
> >         except Empty:
> >             break
>
> > threads = [Thread(target=do_work, args=(lq,)) for _ in
> > range(THREAD_NUM)]
>
> > for t in threads:
> >     t.start()
>
> > while not lq.empty():
> >     try:
> >         time.sleep(1)
> >     except (IOError, InterceptInterrupt):
> >         break
>
> > for t in threads:
> >     t.join()
>
> > if lq.empty():
> >     print("The queue is empty.")
> > else:
> >     print("The queue is NOT empty. Some additional work has to be
> > done.")
>
> > Thank you,
> > Mattia




More information about the Python-list mailing list