Exit python properly - python

I knew that sys.exit() raises an Exit exception, so when I run this I knew it wouldn't exit:
In [25]: try:
....: sys.exit()
....: except:
....: print "oops"
....:
oops
But I thought that os._exit() was meant to exit using a C call, but it's also causing an exception:
In [28]: try:
....: os._exit()
....: except:
....: print "oops"
....:
oops
Is there a way of doing this without killing the PID?

I'm not sure I understand your question, but os._exit isn't raising an exception -- you calling os._exit with the wrong number of arguments is:
try:
os._exit()
except Exception as e:
print e
#output: _exit() takes exactly 1 argument (0 given)

Don't use except without an Exception class, so sys.exit will just work fine without triggering the exception handling:
>>> import sys
>>> try:
... sys.exit()
... except Exception:
... print 'oops'
...
$
There are other exceptions which are triggered with a plain except clause (and in general shouldn't), especially KeyboardInterrupt.

Related

Exit script from inside of try-catch block in Python 3

I'm trying to exit a script from inside a try: except: block except it just goes on to the exception case.
None of these...
try:
exit()
except:
pass()
try:
quit()
except:
pass
import sys
try:
sys.exit()
except:
pass
...exit my script, they just go on to the except case.
How would I exit my script from inside one of these blocks?
All of these examples raise the SystemExit exception and you are catching that exception, a blank except clause will catch all exceptions.
This is the reason why you should always specify the exception you intend to catch or at least use except Exception eg
try:
exit()
except Exception:
pass
try:
quit()
except Exception:
pass
import sys
try:
sys.exit()
except Exception:
pass
With that change in place, all of you examples will cause your Python app to exit

Catch all exceptions except user abort

I have a script that catches all exceptions, which works great unless I want to abort the script manually (with control + c). In this case the abort command appears to be caught by the exception instead of quitting.
Is there a way to exclude this type of error from the exception? For example something as follows:
try:
do_thing()
except UserAbort:
break
except Exception as e:
print(e)
continue
You could just force to exit the program whenever the exception happens:
import sys
# ...
try:
do_thing()
except UserAbort:
break
except KeyboardInterrupt:
sys.exit()
pass
except Exception as e:
print(e)
continue

Break statement in finally block swallows exception

Consider:
def raiseMe( text="Test error" ):
raise Exception( text )
def break_in_finally_test():
for i in range(5):
if i==2:
try:
raiseMe()
except:
raise
else:
print "succeeded!"
finally:
print "testing this!"
break
if __name__=='__main__':
break_in_finally_test()
I expected to see Exception( "Test error" ) to be raised, but instead only "testing this" is printed. The intention, of course, was to call raiseMe() only once, no matter if we succeed or not - but if it raises an exception, I would have wanted to see that!
Why does break swallow the exception that I explicitly raise?
From https://docs.python.org/2.7/reference/compound_stmts.html#finally:
If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception, it is re-raised at the end of the finally clause. If the finally clause raises another exception or executes a return or break statement, the saved exception is discarded
This also reflects the behaviour expected from the try...finally statement before PEP341:
This is how a try except finally block looked like pre PEP341:
try:
try:
raiseMe()
except:
raise
finally:
#here is where cleanup is supposed to happen before raising error
break
#after finally code: raise error
As the raising of errors never happens in the finally block it is never actually raised.
To maintain backwards compatibility with Python<=2.4, it had to be done in this way.
From the docs Error Handling Docs:
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not.
Your exception never gets raised because you break before the try statement gets fully evaluated.
I think upon reflection that it is due to the fact that break actually raises a StopIteration to "break" out of the for-loop. This is really not very intuitive and not particularly well documented (not mentioned on 1, for example). Could maybe someone confirm/explain it better?
Have the following code structure:
def func():
try:
driver.do("something")
except TimeoutException:
pass
finally:
result = driver.do("something else")
return result
Got the exception by pylint:
return statement in finally block may swallow exception (lost-exception)
Solution was to put return out of the finally statement:
def func():
try:
driver.do("something")
except TimeoutException:
pass
finally:
result = driver.do("something else")
return result # <<

in python , why is there a difference in exception when signal handling is done before and after "try except"

I recently started with python . I was playing with handling the keyboard interrupt , when I came across this behavior
import signal,sys
def handleInt(sign,no):
print "interrupted"
signal.signal(signal.SIGINT,handleInt) # exception raised is IOError
try:
sys.stdin.read(1)
except IOError:
print "io interrupt"
but if I change the signal handling to after the try-except
import signal,sys
def handleInt(sign,no):
print "interrupted"
try:
sys.stdin.read(1)
except KeyboardInterrupt:
print "keyboard interrupt"
signal.signal(signal.SIGINT,handleInt) # exception raised is KeyboardInterrupt
When I press ctrl+c , there is a difference in the exception in the two cases .So why is this behavior ?
Python has its own built-in singal handler for SIGINT. This handler simply raises KeyboardInterrupt. In your first code, you replaced the built-in handler with the new handler hence you see this output:
$python test_exc.py
^Cinterrupted
Note that io interrupted is not printed, since no exception was raised. In fact modifying the code to:
import signal,sys
def handleInt(sign,no):
print "interrupted"
signal.signal(signal.SIGINT, handleInt) # exception raised is IOError
try:
sys.stdin.read(1)
except IOError:
print "io interrupt"
else:
# else is executed only if no exception was raised
print "done"
You get:
$python test_exc.py
^Cinterrupted
done
Note that hitting Ctrl+C does not block the call to sys.stdin.read(1) hence you still have to press some key to let the program continue. Raising an exception inside the signal handler will raise it as if the call to sys.stdin.read(1) produced it:
import signal,sys
def handleInt(sign,no):
print "interrupted"
raise OSError
signal.signal(signal.SIGINT, handleInt) # exception raised is IOError
try:
sys.stdin.read(1)
except IOError:
print "io interrupt"
else:
# else is executed only if no exception was raised
print "done"
Sample run:
$python test_exc.py
^Cinterrupted
Traceback (most recent call last):
File "test_exc.py", line 10, in <module>
sys.stdin.read(1)
File "test_exc.py", line 5, in handleInt
raise OSError
OSError
Note: you can access the default signal handler via signal.default_int_handler.
When you try and register the signal after the blocking call to sys.stdin.read, you never actually get there.
So you get an exception when you hit Ctrl-C which raises a KeyboardInterrupt breaks out of the read and is caught by the try.
When you actually register the signal handler in the first example something slightly different is happening. The interrupt is being handled by your handleInt code.

Python: rasing from except causes finally to execute?

Say I have the following code:
try:
[...]
except:
raise Exception([...])
finally:
[code]
My question is: if the code in the try block raises an exception which is caught in except, is [code] from the finally clause executed since a new exception is raised in the except clause? And if so, when is it executed? Before the new exception is raised or after the new exception is propagated through the method stack?
an example is worth a 1000 words, why didn't you just try what you've written?
>>> def foo():
>>> try:
>>> print "2 try block"
>>> raise Exception("1")
>>> print "never printed"
>>> except:
>>> print "3 first except block"
>>> raise Exception("2")
>>> finally:
>>> print "4 finally block"
>>> print "end of function"
>>>
>>> try:
>>> print "1 before foo"
>>> foo()
>>> print "never printed too"
>>> except:
>>> print "5 outter except clause"
1 before foo
2 try block
3 first except block
4 finally block
5 outter except clause
Before the new exception is raised or after the new exception is propagated through the method stack?
so as you can tell from the example, the finally block is called after the except block it has been defined in (i.e. after leaving the try/except/finally block), but before getting to the outer try/except block.
Which is logical, you want the finally to always be triggered when you exit the try block however you exit it, so you can be sure that your code environment is coherent when executing code outside of the try statement (whether you're releasing resources, or resetting values, or rolling back/committing modifications...).
finally is executed no matter the try block succeeds or the except block is run due to exceptions!
even if your except block raises an exception the new exception will be handled by another try catch handler but after executing the finally block, instead of forming a recursive loop:
try:
try:
[...]
except:
raise Exception([...]) #this is line number xyz
finally:
[code]
except:
[...] #this code will be running after line number xyz

Categories