Why does try exits after first statement if it throws an Exception? - python

I am new to python I am learning exception handling now.
try:
print(1/0)
int(input("number"))
import bala
except ZeroDivisionError:
print("Divided by zero")
except KeyboardInterrupt:
print("dont press ctrl C!")
except ValueError:
print("Value should be number")
except ModuleNotFoundError:
print("Module not found")
The above code exits after first exception and the rest of the try statements are not executed. Should I use separate try-except block for each statement? Like this
try:
int(input("number"))
except ValueError:
print("Value should be number")
and
try:
import bala
except ModuleNotFoundError:
print("Module not found")

If an exception is raised that makes Python stop the execution immediately. You can prevent a complete program stop by using a try and except. However if an exception is raised in the try block, it will still stop execution right there and only continue if an appropriate except block catches the Exception (or if there is a finally block).
In short: If you want to continue with the next statements you need to use separate try and except blocks. But if you want to execute the next statements only if the previous statements didn't raise an Exception you shouldn't use separate try and except blocks.

Yes you need to have separate exception blocks because if it gets by the first block, it thinks thats all it needs to get by, so if you want to test every one, you should use separate ones

You have to use multiple try/except blocks.
Once an error is found, anything happening is stopped, and the exception is dealed with.
Think of it as a fire. When there is a fire you stop whatever and run out. For python it deals with the exception

Related

Difference between bare except and specifying a specific exception

In this piece of code, I could write a simple except clause without writing Exception in front of it. I mean the last line could be like this :
except:
print('Hit an exception other than KeyError or NameError!')
What is the point of writing Exception in front of an except clause ?
try:
discounted_price(instrument, discount)
except KeyError:
print("There is a keyerror in your code")
except NameError:
print('There is a TypeError in your code')
except Exception:
print('an exception occured')
I tried writing an except clause without Exception keyword and it worked the same.
Thank you guys for your answers . I know the point of catching specific errors. If I want to ask more clearly , what is the difference between two clauses :
except Exception:
print('an exception occured')
except :
print('an exception occured')
The point of specifying the Exception is that ONLY that Exception will be caught, if you do not specify any Exception, then ALL Errors and Exceptions will be caught potentially masking bugs.
For example let's say that I want to read a file if it exists or otherwise print a message to the user, I can write:
try:
with ope("example.txt", "r") as f:
print(f.read())
except:
print("File not found")
But while this code runs fine without raising any exceptions, this code will never read the file, even if it exists!!!
This is because I wrote ope instead of open and the NameError was caught by my bare except, If I write the except in the correct way:
try:
with ope("example.txt", "r") as f:
print(f.read())
except FileNotFoundError:
print("File not found")
Now I can properly debug my code:
Traceback (most recent call last):
File "/home/riccardo/types.py", line 4, in <module>
with ope("example.txt", "r") as f:
NameError: name 'ope' is not defined
A bare expect
try:
...
except:
pass
or catching any exception whatsoever
try:
...
except Exception:
pass
are bad practice, because you can be hiding bug or be interfering with the normal procedure of the program.
You should only catch exception that you know how to handle, everything else you should let it propagate.
For some example:
Hide bug: it can hide some typo in your code as Caridorc example show making you think that you had a problem different than the real problem
Interfering with the normal procedure: you can make it an unexpectedly unkillable program or get in the way of the normal procedure of the program by discarding an exception that another part of the code was expecting.
like for example
while True:
try:
print("running")
except:
print("I'm immortal muahahaha")
this piece of code now you can't stop with you usual control-z (control-z throw and KeyboardInterrupt exception into your program) so you now need to close the whole interpreter/kill it with the task admin just to stop it, and if this was unintended you just introduced a new bug and depending on what you're doing it can be catastrophic.
To illustrate how catastrophic it can be, consider the following hypothetical case: imagine you make so benign function for a medical device and you put something like this
try:
...
except:
print("some error happens")
now it just so happens that while you piece of code was running a HeartAttack exception was raised and your catch it all and ignore piece of code will do, well, just that, and here is the twist this device was a pacemaker... well, congratulation you just killed the poor guy.
And that is why you should only catch the exception you know how to deal with, everything else you let it pass and hope that somebody along the line know how to deal with it, like in the example above, you and your piece of code don't know how to deal with a HeartAttack, but the pacemaker do and the pacemaker was the one that call your piece of code let it deal with it...
for a no so extreme example consider this simple code
def get_number_from_user():
while True:
try:
return int(input("write a number: "))
except:
print("not a valid number try again")
if your user was done with your program and this happens to be the thing running he/she might want to kill it with a control-z as you usually do with any program, but it will find that it doesn't work, the correct way here is to catch the error we know how to deal with in this case, namely ValueError, everything else isn't this function business
def get_number_from_user():
while True:
try:
return int(input("write a number: "))
except ValueError:
print("not a valid number try again")
You also ask about the difference between
try:
...
except:
pass
and this
try:
...
except Exception:
pass
the difference is that a bare except can catch any and all kind of exception, that in python is anything that is or inherit from BaseException that sit at the top of the exception hierarchy, while except Exception will catch only Exception itself or anything that inherit from it (the same apply for any particular exception you put there), this small distinction allow to make some exceptions more special than other, like the aforementioned KeyboardInterrupt that inherit from BaseException instead of Exception, and that is used to signal that the user wants to terminate this program, so you should do so and this distinction is made basically so new programmers don't shoot themselves in the foot when using except Exception
Just to add to the answer provided by #Caridorc, by specifying each error separately, you can run specific error handling code pertaining to that error when the exception arises. If for example the file does not exist, you can print message to that effect. If however, it fails to print because you mistyped g instead of f, you can print a message to say that the variable is not recognised ( separate code for separate error captures). For exmple:
g = 100 # Unrelated variable declared previously
try:
with open("example.txt", "r") as f:
x=print(f.read())
except FileNotFoundError:
print("File not found")
except AttributeError:
print("Reading wrong variable")
except Exception as e:
print("Unknown Error", e)
Note also the last exception except Exception as e:. This is the same as just except: but allows you to handle all other errors that do not fit onto previous captures and retrieve e - the error message that is generated by compiler. There is effectively no difference between except: and except Exception: in terms of execution
Consider the code:
a = 5
b = 0
x = a / b
Executing this will alert you to the fact that you have attempted to divide a float by zero but it will crash your code.
Now consider:
a = 5
b = 0
try:
x = a / b
except: # or 'except Exception:'
print("An exception was raised")
This will raise an exception that is handled by printing a message that an error occurred. You code will not crash but you do not know how to properly handle the code because you do not know what the exception was, just that one occurred.
Now consider:
a = 5
b = 0
try:
x = a / b
except Exception as e:
print("An exception was raised, generating error", e)
Now your code does not crash. Is handled and you know what the error was.
The purpose of writing "Exception" in front of an except clause is to catch all possible exceptions that can occur in the code. By specifying "Exception", you are telling the interpreter to handle any type of exception that might be raised. The more specific the exception specified in the except clause, the more targeted the handling of the exception can be. For example, if you only want to handle "KeyError" exceptions, you can specify that explicitly in the except clause, as in the first example.

python ignore whichever line that causes error and continue running the code after that line

I understand the try/except method. What I'm trying to do is:
try:
some_func1() #potentially raises error too
do_something_else() #error was raised
continue_doing_something_else() #continues here after handling error
except:
pass
In the above code, when the error is raised at do_something_else(), the error is handled but then the try statement is exited.
What I want is for python to continue whatever code that is after the line that causes the error. Assuming that an error can happen anywhere in the try statement so I can't just wrap the try/except around do_something_else() itself, is there a way to do this in python?
What you want to do (try with restart) is not possible in Python. Lisp can do it (http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html), and you can implement it in Scheme using call/cc.
Just put the code that you want to do after the possible exception after the except. You may want to use finally (see https://docs.python.org/3/tutorial/errors.html for the documentation):
try:
some_func1()
do_something_else() #error was raised
except:
handle_exception()
finally:
continue_doing_something_else() #continues here after handling error or if no error occurs
if continue_doing_something_else() can also throw exceptions, then put that in a try/except too:
try:
some_func1()
do_something_else() #error was raised
except:
handle_exception1()
try:
continue_doing_something_else()
except:
handle_exception2()
finally:
any_cleanup()
as a general rule, your exception handling should be kept as small in scope as possible while remaining sensible, consider excepting only the 'expected' exceptions and not all of them (e.g. except OSError: when attempting to open files)

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...

Python reraise/recatch exception

I would like to know if it is possible in python to raise an exception in one except block and catch it in a later except block. I believe some other languages do this by default.
Here is what it would look like"
try:
something
except SpecificError as ex:
if str(ex) = "some error I am expecting"
print "close softly"
else:
raise
except Exception as ex:
print "did not close softly"
raise
I want the raise in the else clause to trigger the final except statement.
In actuality I am not printing anything but logging it and I want to log more in the case that it is the error message that I am not expecting. However this additional logging will be included in the final except.
I believe one solution would be to make a function if it does not close softly which is called in the final except and in the else clause. But that seems unnecessary.
What about writing 2 try...except blocks like this:
try:
try:
something
except SpecificError as ex:
if str(ex) == "some error I am expecting"
print "close softly"
else:
raise ex
except Exception as ex:
print "did not close softly"
raise ex
Only a single except clause in a try block is invoked. If you want the exception to be caught higher up then you will need to use nested try blocks.
As per python tutorial there is one and only one catched exception per one try statement.
You can find pretty simple example in tutorial that will also show you how to correctly use error formatting.
Anyway why do you really need second one? Could you provide more details on this?
You can do this using the six package.
Six provides simple utilities for wrapping over differences between Python 2 and Python 3.
Specifically, see six.reraise:
Reraise an exception, possibly with a different traceback. In the simple case, reraise(*sys.exc_info()) with an active exception (in an except block) reraises the current exception with the last traceback. A different traceback can be specified with the exc_traceback parameter. Note that since the exception reraising is done within the reraise() function, Python will attach the call frame of reraise() to whatever traceback is raised.

How to see the error and still keep the program on in the Python shell?

I know try/except can handle errors in my program.
But, is there a way of making the error be displayed in the program execution, be ignored and let the execution go on?
In VBScript and other VB-derived languages, you can get this sort of behavior with "ON ERROR GOTO NEXT".
No such behavior exists in Python. Even if you wrap each top-level statement like:
try:
do_something()
except Exception as e:
print e
try:
do_something_else()
except Exception as e:
print e
you'd still have the result that statements within do_something are skipped at the point the exception is thrown.
Though perhaps if you have a particular use-case in mind, there may be other acceptable answers. For instance, in a top-level loop:
while True:
cmd = get_command()
if cmd == 'quit': break
try:
run_command(cmd)
except Exception as e:
print "Error running " + cmd + ":"
print e
import traceback
try:
# do whatever you want
except Exception:
traceback.print_exc()
Of course you should be more specific in a real scenario, i.e. you shouldn't catch and ignore all Exception instances, only the ones you are interested in and you know that they are safe to ignore.
Also note that if an exception happens somewhere within the try..except block, the execution will continue after the try..except block, not at the next statement. This is probably the closest to what you want to achieve.

Categories