Python thread class - exiting threads - python

I am using thread to invoke a function which runs as :
def fillIQ(ipno):
global inp_width
global no_exit
try:
while 1 :
if no_exit==1:
sys.exit() # <exit line>
tags=[]
for i in range(ipno):
yn=random.randint(0,1)
if yn==1:
voqno=random.randint(0,ipno-1)
if inpQ[i][voqno]<10:
inpQ[i][voqno]+=1
tag="iq"
tags.append(tag)
d.update()
time.sleep(2)
d.delete("iq")
drawIQ(ipno)
except BaseException ,e:
print "fillIQ > "+e
I am changing the value of no_exit in the main function. But once I change it the thread is not getting exit. Because next time I create a thread for another instance with different inputs( its a GUI program. for one input i execute the thread and later, change input and execute it again) the odler thread appears to run.

To exit a thread you must either return from it or raise SystemExit(). Returning actually raises a SystemExit exception in the context of a thread. But you are catching that exception and not re-raising it.
>>> isinstance(SystemExit(1), BaseException)
True
There's your problem. Either catch SystemExit exceptions separately and re-raise it explicitly, or be more selective with your general catching, or re-raise everything you catch. For brevity, I give an example of the former
except SystemExit:
raise
except BaseException:
print "fillIQ > ", e
Also, note that it's , e and not +e since e is not a string. There were a couple of other issues I encountered just trying to get your thread to run, but I'm sure you'll figure them out quickly enough, mostly missing imports and other values that are not listed in your example.

Related

exit(1) in signal handler just gets caught as SystemExit as there is nothing to it

I have an application that looks like this:
while True:
try:
self.try_to_read_usb_device()
break
except:
time.sleep(1)
I also have an SIGALRM handler which is supposed to exit the program in case it got stuck somewhere:
def alarm_signal_handler(signal, frame):
# Something went wrong
exit(1)
However the exit(1) just get caught by the try/except and gets discarded as this is what that specific except does.
This is quite unexpected to me.
In the complete application there will be a lot of try/except and I don't see myself adding
except SystemExit:
exit(1)
or something for all of them.
Any idea how I should handle that use-case?
The dirty way
You can use os._exit instead of sys.exit.
Note that this has obvious drawbacks exactly because it won't go through an exception:
Exit the process with status n, without calling cleanup handlers, flushing stdio buffers, etc.
The proper way
I'd recommend to instead change your exception handling to catch only things inheriting from Exception, because SystemExit doesn't inherit from Exception for precisely this reason, so it won't be caught accidentally:
except Exception:
See also the SystemExit documentation:
This exception is raised by the sys.exit() function. It inherits from BaseException instead of Exception so that it is not accidentally caught by code that catches Exception. This allows the exception to properly propagate up and cause the interpreter to exit.
This also applies to KeyboardInterrupt by the way - Ctrl+C will be caught by except: but not by except Exception:.
It's illustrated pretty well in the exception hierarchy diagram in the Python docs, which you can find here.

How does an exception know if it's being handled?

When raised, SystemExit causes the interpreter to exit, unless the exception is handled.
try:
raise SystemExit()
except SystemExit:
print('not today')
# Continue flow...
I want to mimic that behavior and write my own exception which executes some code only if the exception isn't caught.
Obviously this wouldn't work:
class MyFatalError(Exception):
def __init__(self):
import sys
sys.exit()
try:
raise MyFatalError()
except MyFatalError:
print('never gets here')
(...because an __init__ executes on instantiation, regardless of whether the error is handled.)
Is there a (straightforward and pythonic) way to make an exception behave differently when being handled?
You should not be thinking of SystemExit as a normal exception. All higher-level languages have a function to shut down the process immediately, and that would be sys._exit() in python, but there is also sys.exit() that does kinda the same, but allows your finally blocks to run first, and is implemented as an exception.
What you want should be done by having a try - except block at the lowest level of your application. The behaviour should be in the handler code, not in the exception.

KeyboardInterrupt not raised or caught in the case of broad Exception

Could somebody explain to me the following. Lets take a look at the code:
if __name__ == '__main__':
try:
while 1:
x = 2+2
except KeyboardInterrupt:
print('yo')
If I run this, wait for a while, then press Ctrl+C, an exception will be processed and the message yo will be printed.
If we change the code to catch a broad exception like this:
if __name__ == '__main__':
try:
while 1:
x = 2+2
except Exception, e:
print('yo')
print(e)
Run it, wait for a while, press Ctrl+C, the KeyboardInterrupt exception will not be caught.
According to Python documentation:
Python installs a small number of signal handlers by default: SIGPIPE is ignored (so write errors on pipes and sockets can be reported as ordinary Python exceptions) and SIGINT is translated into a KeyboardInterrupt exception. All of these can be overridden.
So, why in the second case is this exception not caught or even raised?
You cannot catch KeyboardInterrupt by catching Exception because the former inherits from BaseException only. You can read about this in the docs:
exception KeyboardInterrupt
Raised when the user hits the interrupt key (normally Control-C or Delete). During execution, a check for interrupts is made regularly.
Interrupts typed when a built-in function input() or raw_input() is
waiting for input also raise this exception. The exception inherits
from BaseException so as to not be accidentally caught by code that
catches Exception and thus prevent the interpreter from exiting. (Emphasis mine)
This means that you would have to do:
except BaseException, e:
But that is considered a bad practice. It would be better to just catch KeyboardInterrupt itself like in your first example.

Python: catch any exception and put it in a variable

To figure out what it would take to avoid some recursion, I need to catch any exception (edit: Not just ones derived from Exception, but all exceptions, including KeyboardInterrupt and user exceptions), put it in a variable, and later re-raise it outside the catch block. Essentially, I'm trying to roll my own finally block. Is this possible?
The actual problem is to call a number of cleanup functions, and if any of them fail, all the others should also be called, then the exception for the one that failed should still propagate. Here's my current solution, it takes a list of Popen objects:
def cleanupProcs(procs):
if not procs:
return
proc = procs.pop(0)
try:
proc.terminate()
proc.wait()
finally:
cleanupProcs(procs)
Is there an iterative way to do this? A more elegant way? A more Pythonic way?
If you want the stacktrace included:
try:
# something
except:
the_type, the_value, the_traceback = sys.exc_info()
later
raise the_type, the_value, the_traceback
(Related to this answer)
See also here for Python 2.7.
In this case, I think I would argue that you may not be doing it right.
To me, the point of an exception is to signal a bum bum baaaaa exceptional circumstance. And when you are writing code that may fire an exception you have two responsible options - catch it and do something with it (like recover), or completely ignore it.
From what you say in your post, you don't really care that an exception happened. It shouldn't halt your program, and program flow should continue as normal. You do however want to know that an exception happened. And this is where the logging module comes in:
import logging
log = logging
def get_some_cheese():
raise ValueError("Sorry, we're right out.")
try:
get_some_cheese()
except:
log.exception("What a waste of life")
When you log an exception it automagically adds stack trace information for you. After you config your logging a bit, you can get it setup to do all sorts of whatever things you want to do - send an email, write to a file or stdout/err, whatever. But then you'll get informed that an exception occured, but you can also simply recover from the error and continue on your merry way cleaning up whatever it is you need to clean up.
I'd probably use BaseException to catch anything that gets thrown, and iterate through all your cleanup functions (instead of using recursion). Then append any exceptions to a list, to deal with (re-raise, log, etc) as appropriate when you finish the cleanup.
def runCleanup(procs):
exceptions = []
for proc in procs:
try:
proc.terminate()
proc.wait()
except BaseException as e:
exceptions.append(e) # Use sys.exc_info() for more detail
return exceptions # To be handled or re-raised as needed
you can use:
procexceptions = []
except Exception, e:
procexceptions.append(e)
and then later (after the loop for terminating processes) you can
raise procexceptions[0]
etc.
Openstack does something very similar for a different reason. Have a look at https://github.com/openstack/nova/blob/master/nova/openstack/common/excutils.py#L30 (function save_and_reraise_exception). In their case it works like a resource manager.
Like just about everything else in Python, exceptions are objects and therefore can be bound to names and operated upon. Here's a short example showing how to grab an exception and use it later:
>>> def to_int(x):
... try:
... return int(x)
... except Exception, e:
... print 'in exception block:', e
... print 'after exception block:', e
>>> to_int('12')
12
>>> to_int('abc')
in exception block: invalid literal for int() with base 10: 'abc'
after exception block: invalid literal for int() with base 10: 'abc'
Thats easy:
>>> try:
... #something
... except BaseException, e: # OK. Using BaseException instead of Exception
... pass
...
>>>
>>> raise e
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>>

Why finally block is executing after calling sys.exit(0) in except block?

I'm new to Python. I just want to know why the finally block is executing after calling sys.exit(0) in the except block?
Code:
import sys
def divide_by_zero():
try:
10/0
print "It will never print"
except Exception:
sys.exit(0)
print "Printing after exit"
finally:
print "Finally will always print"
divide_by_zero()
Btw., I was just trying to do the same thing as in Java, where the finally block is not executed when System.exit(0) is in the catch block.
All sys.exit() does is raise an exception of type SystemExit.
From the documentation:
Exit from Python. This is implemented by raising the SystemExit
exception, so cleanup actions specified by finally clauses of try
statements are honored, and it is possible to intercept the exit
attempt at an outer level.
If you run the following, you'll see for yourself:
import sys
try:
sys.exit(0)
except SystemExit as ex:
print 'caught SystemExit:', ex
As an alternative, os._exit(n) with the status code will stop the process bypassing much of the cleanup, including finally blocks etc.
You should use os._exit(0).
About your example:
A finally clause is always executed before leaving the try statement,
whether an exception has occurred or not.
This is from Error and Exceptions part of Python docs. So - your finally block will always be executed in example you show unless you will use os._exit(0). But you should use it wisely...

Categories