On Jan 4, 3:12 pm, Fuzzyman <fuzzy...@gmail.com> wrote: > On Dec 29 2010, 11:31 pm, gervaz <ger...@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 -- http://mail.python.org/mailman/listinfo/python-list